Merge "Use image native api in volume tests"
diff --git a/releasenotes/notes/add-kwargs-to-delete-vol-of-vol-client-1ecde75beb62933c.yaml b/releasenotes/notes/add-kwargs-to-delete-vol-of-vol-client-1ecde75beb62933c.yaml
new file mode 100644
index 0000000..b8c9dfc
--- /dev/null
+++ b/releasenotes/notes/add-kwargs-to-delete-vol-of-vol-client-1ecde75beb62933c.yaml
@@ -0,0 +1,7 @@
+---
+features:
+ - |
+ The ``delete_volume`` method of the ``VolumesClient`` class
+ now has an additional ``**params`` argument that enables passing
+ additional information in the query string of the HTTP request.
+
diff --git a/releasenotes/notes/add-volume-backup-force-delete-af0156651a0cbf7f.yaml b/releasenotes/notes/add-volume-backup-force-delete-af0156651a0cbf7f.yaml
new file mode 100644
index 0000000..71bbfcb
--- /dev/null
+++ b/releasenotes/notes/add-volume-backup-force-delete-af0156651a0cbf7f.yaml
@@ -0,0 +1,9 @@
+---
+features:
+ - |
+ As in the [doc]:
+ https://developer.openstack.org/api-ref/block-storage/v3/
+ #force-delete-a-backup.
+
+ * Force-deletes a backup(v2)
+
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index b2c33e2..91e9684 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -82,9 +82,9 @@
self.assertEqual(min_img_ram, image['min_ram'])
# Try to create server with flavor of insufficient ram size
- self.assertRaisesRegexp(lib_exc.BadRequest,
- "Flavor's memory is too small for "
- "requested image",
- self.create_test_server,
- image_id=image['id'],
- flavor=flavor['id'])
+ self.assertRaisesRegex(lib_exc.BadRequest,
+ "Flavor's memory is too small for "
+ "requested image",
+ self.create_test_server,
+ image_id=image['id'],
+ flavor=flavor['id'])
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index cce9856..96983b0 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import testtools
+
from tempest.api.compute.floating_ips import base
from tempest import config
from tempest.lib.common.utils import data_utils
@@ -99,3 +101,27 @@
self.assertRaises((lib_exc.NotFound, lib_exc.BadRequest),
self.client.associate_floating_ip_to_server,
'', self.server_id)
+
+ @decorators.attr(type=['negative'])
+ @decorators.idempotent_id('58a80596-ffb2-11e6-9393-fa163e4fa634')
+ @test.services('network')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
+ def test_associate_ip_to_server_with_floating_ip(self):
+ # The VM have one port
+ # Associate floating IP A to the VM
+ # Associate floating IP B which is from same pool with floating IP A
+ # to the VM, should raise BadRequest exception
+ body = self.client.create_floating_ip(
+ pool=CONF.network.public_network_id)['floating_ip']
+ self.addCleanup(self.client.delete_floating_ip, body['id'])
+ self.client.associate_floating_ip_to_server(body['ip'], self.server_id)
+ self.addCleanup(self.client.disassociate_floating_ip_from_server,
+ body['ip'], self.server_id)
+
+ body = self.client.create_floating_ip(
+ pool=CONF.network.public_network_id)['floating_ip']
+ self.addCleanup(self.client.delete_floating_ip, body['id'])
+ self.assertRaises(lib_exc.BadRequest,
+ self.client.associate_floating_ip_to_server,
+ body['ip'], self.server_id)
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 339b4bb..0a163fc 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -232,10 +232,12 @@
# For example, when creating a trust, we will set the expiry time of
# the trust to 2015-02-17T17:34:01.907051Z. However, if we make a GET
# request on the trust, the response will contain the time rounded up
- # to 2015-02-17T17:34:02.000000Z. That is why we shouldn't set flag
- # "subsecond" to True when we invoke timeutils.isotime(...) to avoid
- # problems with rounding.
- expires_str = timeutils.isotime(at=expires_at)
+ # to 2015-02-17T17:34:02.000000Z. That is why we set microsecond to
+ # 0 when we invoke isoformat to avoid problems with rounding.
+ expires_at = expires_at.replace(microsecond=0)
+ # NOTE(ekhugen) Python datetime does not support military timezones
+ # since we used UTC we'll add the Z so our compare works.
+ expires_str = expires_at.isoformat() + 'Z'
trust = self.create_trust(expires=expires_str)
self.validate_trust(trust, expires=expires_str)
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index afc3281..a6f9246 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -121,7 +121,7 @@
'available')
@decorators.idempotent_id('47a35425-a891-4e13-961c-c45deea21e94')
- def test_volume_backup_reset_status(self):
+ def test_volume_backup_reset_status_force_delete(self):
# Create a volume
volume = self.create_volume()
# Create a backup
@@ -136,3 +136,6 @@
status="error")
waiters.wait_for_volume_resource_status(self.admin_backups_client,
backup['id'], 'error')
+ # Force delete a backup volume when backup is in error state.
+ self.admin_backups_client.force_delete_backup(backup['id'])
+ self.admin_backups_client.wait_for_resource_deletion(backup['id'])
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 13b3e4d..d8b503d 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -143,7 +143,8 @@
snapshot['id'], 'available')
return snapshot
- def create_backup(self, volume_id, backup_client=None, **kwargs):
+ def create_backup(self, volume_id, backup_client=None,
+ wait_until="available", **kwargs):
"""Wrapper utility that returns a test backup."""
if backup_client is None:
backup_client = self.backups_client
@@ -153,9 +154,12 @@
backup = backup_client.create_backup(
volume_id=volume_id, **kwargs)['backup']
- self.addCleanup(backup_client.delete_backup, backup['id'])
- waiters.wait_for_volume_resource_status(backup_client, backup['id'],
- 'available')
+
+ self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+ backup_client.delete_backup, backup['id'])
+ waiters.wait_for_volume_resource_status(backup_client,
+ backup['id'],
+ wait_until)
return backup
# NOTE(afazekas): these create_* and clean_* could be defined
diff --git a/tempest/config.py b/tempest/config.py
index b8a91b7..e23cc99 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -392,9 +392,9 @@
"migration"),
cfg.BoolOpt('block_migrate_cinder_iscsi',
default=False,
- help="Does the test environment block migration support "
- "cinder iSCSI volumes. Note, libvirt doesn't support this, "
- "see https://bugs.launchpad.net/nova/+bug/1398999"),
+ help="Does the test environment support block migration with "
+ "Cinder iSCSI volumes. Note: libvirt >= 1.2.17 is required "
+ "to support this if using the libvirt compute driver."),
cfg.BoolOpt('vnc_console',
default=False,
help='Enable VNC console. This configuration value should '
diff --git a/tempest/lib/services/volume/v2/backups_client.py b/tempest/lib/services/volume/v2/backups_client.py
index 2b5e82d..197d57e 100644
--- a/tempest/lib/services/volume/v2/backups_client.py
+++ b/tempest/lib/services/volume/v2/backups_client.py
@@ -55,6 +55,14 @@
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)
+ def force_delete_backup(self, backup_id):
+ """Force delete a backup volume."""
+ post_body = json.dumps({'os-force_delete': {}})
+ url = 'backups/%s/action' % backup_id
+ resp, body = self.post(url, post_body)
+ self.expected_success(202, resp.status)
+ return rest_client.ResponseBody(resp)
+
def show_backup(self, backup_id):
"""Returns the details of a single backup."""
url = "backups/%s" % backup_id
diff --git a/tempest/lib/services/volume/v2/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index c67ddfb..43fc9b8 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -118,11 +118,16 @@
self.expected_success(200, resp.status)
return rest_client.ResponseBody(resp, body)
- def delete_volume(self, volume_id, cascade=False):
- """Deletes the Specified Volume."""
+ def delete_volume(self, volume_id, **params):
+ """Deletes the Specified Volume.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/block-storage/v2/#delete-volume
+ """
url = 'volumes/%s' % volume_id
- if cascade:
- url += '?cascade=True'
+ if params:
+ url += '?%s' % urllib.urlencode(params)
resp, body = self.delete(url)
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)