Skip to content

Commit

Permalink
Merge branch 'add-resumable-for-2-x' into 2.14.13-build
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammed AbuAisha committed Nov 5, 2019
2 parents 03219e7 + 513d96b commit 4b70c45
Show file tree
Hide file tree
Showing 32 changed files with 1,034 additions and 130 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
2.14.13:
- Add support for resumable actions.
2.14.12:
- expose ipv4 and ipv6 addresses as runtime properties for port.
2.14.11:
Expand Down
31 changes: 25 additions & 6 deletions cinder_plugin/tests/test_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,13 @@ def test_delete(self):
self.assertTrue(OPENSTACK_NAME_PROPERTY
not in ctx_m.instance.runtime_properties)

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
@mock.patch('openstack_plugin_common.NovaClientWithSugar')
@mock.patch('openstack_plugin_common.CinderClientWithSugar')
@mock.patch.object(volume, 'wait_until_status', return_value=(None, True))
def test_attach(self, wait_until_status_m, cinder_m, nova_m):
def test_attach(self, wait_until_status_m, cinder_m, nova_m, *_):
volume_id = '00000000-0000-0000-0000-000000000000'
server_id = '11111111-1111-1111-1111-111111111111'
device_name = '/dev/fake'
Expand Down Expand Up @@ -273,35 +276,51 @@ def _test_cleanup__after_attach_fails(
num_tries=10,
timeout=2)

def test_cleanup_after_waituntilstatus_throws_recoverable_error(self):
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_cleanup_after_waituntilstatus_throws_recoverable_error(self, *_):
err = cfy_exc.RecoverableError('Some recoverable error')
with mock.patch.object(volume, 'wait_until_status',
side_effect=[err, (None, True)]) as wait_mock:
self._test_cleanup__after_attach_fails(type(err), True, wait_mock)

def test_cleanup_after_waituntilstatus_throws_any_not_nonrecov_error(self):
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_cleanup_after_waituntilstatus_throws_any_not_nonrecov_error(self,
*_):
class ArbitraryNonRecoverableException(Exception):
pass
err = ArbitraryNonRecoverableException('An exception')
with mock.patch.object(volume, 'wait_until_status',
side_effect=[err, (None, True)]) as wait_mock:
self._test_cleanup__after_attach_fails(type(err), True, wait_mock)

def test_cleanup_after_waituntilstatus_lets_nonrecov_errors_pass(self):
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_cleanup_after_waituntilstatus_lets_nonrecov_errors_pass(self, *_):
err = cfy_exc.NonRecoverableError('Some non recoverable error')
with mock.patch.object(volume, 'wait_until_status',
side_effect=[err, (None, True)]) as wait_mock:
self._test_cleanup__after_attach_fails(type(err), False, wait_mock)

@mock.patch.object(volume, 'wait_until_status', return_value=(None, False))
def test_cleanup_after_waituntilstatus_times_out(self, wait_mock):
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_cleanup_after_waituntilstatus_times_out(self, wait_mock, *_):
self._test_cleanup__after_attach_fails(cfy_exc.RecoverableError, True,
wait_mock)

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
@mock.patch('openstack_plugin_common.NovaClientWithSugar')
@mock.patch('openstack_plugin_common.CinderClientWithSugar')
@mock.patch.object(volume, 'wait_until_status', return_value=(None, True))
def test_detach(self, wait_until_status_m, cinder_m, nova_m):
def test_detach(self, wait_until_status_m, cinder_m, nova_m, *_):
volume_id = '00000000-0000-0000-0000-000000000000'
server_id = '11111111-1111-1111-1111-111111111111'
attachment_id = '22222222-2222-2222-2222-222222222222'
Expand Down
11 changes: 7 additions & 4 deletions cinder_plugin/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def _set_volume_runtime_properties(volume):
ctx.node.properties.get('boot', False)


@operation
@operation(resumable=True)
@with_cinder_client
def create(cinder_client,
args={},
Expand Down Expand Up @@ -158,7 +158,7 @@ def _delete_backup(cinder_client, search_opts):
retry_after=30)


@operation
@operation(resumable=True)
@with_cinder_client
def delete(cinder_client, **kwargs):
# seach snapshots for volume
Expand Down Expand Up @@ -204,6 +204,7 @@ def _get_snapshot_name(ctx, kwargs):
return "vol-{}-{}".format(get_openstack_id(ctx), kwargs["snapshot_name"])


@operation(resumable=True)
@with_cinder_client
def snapshot_create(cinder_client, **kwargs):
volume_id = get_openstack_id(ctx)
Expand All @@ -224,6 +225,7 @@ def snapshot_create(cinder_client, **kwargs):
metadata=None)


@operation(resumable=True)
@with_cinder_client
def snapshot_apply(cinder_client, **kwargs):
volume_id = get_openstack_id(ctx)
Expand Down Expand Up @@ -254,6 +256,7 @@ def snapshot_apply(cinder_client, **kwargs):
ctx.logger.error("Apply snapshot is unsuported")


@operation(resumable=True)
@with_cinder_client
def snapshot_delete(cinder_client, **kwargs):
volume_id = get_openstack_id(ctx)
Expand All @@ -279,14 +282,14 @@ def snapshot_delete(cinder_client, **kwargs):
_delete_snapshot(cinder_client, search_opts)


@operation
@operation(resumable=True)
@with_cinder_client
def creation_validation(cinder_client, **kwargs):
validate_resource(ctx, cinder_client, VOLUME_OPENSTACK_TYPE,
VOLUME_OPENSTACK_ID_KEY)


@operation
@operation(resumable=True)
@with_cinder_client
def list_volumes(cinder_client, args, **kwargs):
volume_list = cinder_client.volumes.list(**args)
Expand Down
8 changes: 4 additions & 4 deletions glance_plugin/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
REQUIRED_PROPERTIES = ['container_format', 'disk_format']


@operation
@operation(resumable=True)
@with_glance_client
def create(glance_client, args, **kwargs):
if use_external_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE):
Expand Down Expand Up @@ -72,7 +72,7 @@ def _get_image_by_ctx(glance_client, ctx):
image_id=get_openstack_id(ctx))


@operation
@operation(resumable=True)
@with_glance_client
def start(glance_client, start_retry_interval, **kwargs):
img = _get_image_by_ctx(glance_client, ctx)
Expand All @@ -82,7 +82,7 @@ def start(glance_client, start_retry_interval, **kwargs):
retry_after=start_retry_interval)


@operation
@operation(resumable=True)
@with_glance_client
def delete(glance_client, **kwargs):
_remove_protected(glance_client)
Expand All @@ -107,7 +107,7 @@ def update(glance_client, args, **kwargs):
set_openstack_runtime_properties(ctx, image, IMAGE_OPENSTACK_TYPE)


@operation
@operation(resumable=True)
@with_glance_client
def creation_validation(glance_client, **kwargs):
validate_resource(ctx, glance_client, IMAGE_OPENSTACK_TYPE)
Expand Down
3 changes: 3 additions & 0 deletions glance_plugin/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ class TestStartImage(unittest.TestCase):
'test-image-start.yaml')

@mock.patch('glance_plugin.image.create')
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
@workflow_test(blueprint_path, copy_plugin_yaml=True)
def test_image_lifecycle_start(self, cfy_local, *_):
test_vars = {
Expand Down
11 changes: 7 additions & 4 deletions keystone_plugin/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
ROLES = 'roles'


@operation
@operation(resumable=True)
@with_keystone_client
def create(keystone_client, args, **kwargs):
if use_external_resource(ctx, keystone_client, PROJECT_OPENSTACK_TYPE):
Expand All @@ -61,7 +61,7 @@ def create(keystone_client, args, **kwargs):
set_openstack_runtime_properties(ctx, project, PROJECT_OPENSTACK_TYPE)


@operation
@operation(resumable=True)
def start(quota_dict, **kwargs):
users = ctx.node.properties[USERS]
validate_users(users, **kwargs)
Expand All @@ -71,7 +71,7 @@ def start(quota_dict, **kwargs):
update_project_quota(quota=quota, **kwargs)


@operation
@operation(resumable=True)
@with_keystone_client
@with_nova_client
@with_cinder_client
Expand All @@ -87,7 +87,6 @@ def delete(keystone_client, nova_client, cinder_client,
RUNTIME_PROPERTIES_KEYS)


@operation
@with_keystone_client
def creation_validation(keystone_client, **kwargs):
validate_resource(ctx, keystone_client, PROJECT_OPENSTACK_TYPE)
Expand Down Expand Up @@ -163,6 +162,7 @@ def delete_quota(project_id, quota, client, what_quota):
'Deleted {0} quota'.format(what_quota))


@operation(resumable=True)
@with_nova_client
@with_neutron_client
@with_cinder_client
Expand All @@ -177,12 +177,14 @@ def update_project_quota(nova_client,
update_quota(project_id, quota, cinder_client, CINDER)


@operation(resumable=True)
@with_keystone_client
def list_projects(keystone_client, args, **kwargs):
projects_list = keystone_client.projects.list(**args)
add_list_to_runtime_properties(ctx, PROJECT_OPENSTACK_TYPE, projects_list)


@operation(resumable=True)
@with_nova_client
@with_neutron_client
@with_cinder_client
Expand All @@ -198,6 +200,7 @@ def get_project_quota(nova_client,
ctx.instance.runtime_properties[QUOTA] = quota


@operation(resumable=True)
@with_keystone_client
def update_project(keystone_client, args, **kwargs):

Expand Down
21 changes: 21 additions & 0 deletions keystone_plugin/tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ def mock_ctx(self, test_vars, test_id,

@mock.patch('openstack_plugin_common._handle_kw',
autospec=True, return_value=None)
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_keystone_project_create_and_delete(self, *_):
quota = {'nova': {'cpu': 120},
'neutron': {'networks': 100}}
Expand Down Expand Up @@ -122,6 +125,9 @@ def test_keystone_project_create_and_delete(self, *_):
self.assertNotIn(OPENSTACK_TYPE_PROPERTY,
ctx.instance.runtime_properties)

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_assign_user(self, *_):
test_vars = {
'project': {},
Expand All @@ -146,6 +152,9 @@ def test_assign_user(self, *_):
self.assertEqual({self.test_user: self.test_role},
mock_project._users)

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_assign_users_not_unique(self, *_):
test_vars = {
'project': {},
Expand All @@ -171,6 +180,9 @@ def test_assign_users_not_unique(self, *_):
cinder_client=mock.MagicMock(), # cinder_client
neutron_client=mock.MagicMock()) # neutron_client

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_assign_user_roles_not_unique(self, *_):
test_vars = {
'project': {},
Expand All @@ -194,6 +206,9 @@ def test_assign_user_roles_not_unique(self, *_):
cinder_client=mock.MagicMock(), # cinder_client
neutron_client=mock.MagicMock()) # neutron_client

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_update_project(self, *_):
test_vars = {
'project': {},
Expand All @@ -215,6 +230,9 @@ def test_update_project(self, *_):
ctx.instance.runtime_properties[
OPENSTACK_NAME_PROPERTY])

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_list_projects(self, *_):
test_vars = {
'project': {},
Expand All @@ -237,6 +255,9 @@ def test_list_projects(self, *_):
self.assertEqual(1,
len(ctx.instance.runtime_properties[project_list]))

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_get_quota(self, *_):
nova_quota = {'cpu': 120}
cinder_quota = {'volumes': 30}
Expand Down
9 changes: 9 additions & 0 deletions keystone_plugin/tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ def mock_ctx(self, test_vars, test_id,

@mock.patch('openstack_plugin_common._handle_kw',
autospec=True, return_value=None)
@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_keystone_user_create_and_delete(self, *_):
test_vars = {
'user': {},
Expand Down Expand Up @@ -100,6 +103,9 @@ def test_keystone_user_create_and_delete(self, *_):
self.assertNotIn(OPENSTACK_TYPE_PROPERTY,
ctx.instance.runtime_properties)

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_update_user(self, *_):
test_vars = {
'user': {},
Expand All @@ -117,6 +123,9 @@ def test_update_user(self, *_):
ctx.instance.runtime_properties[
OPENSTACK_NAME_PROPERTY])

@mock.patch('openstack_plugin_common'
'._check_valid_resource_id_with_operation',
autospec=True, return_value=True)
def test_list_users(self, *_):
test_vars = {
'user': {},
Expand Down
7 changes: 4 additions & 3 deletions keystone_plugin/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
RUNTIME_PROPERTIES_KEYS = COMMON_RUNTIME_PROPERTIES_KEYS


@operation
@operation(resumable=True)
@with_keystone_client
def create(keystone_client, args, **kwargs):
if use_external_resource(ctx, keystone_client, USER_OPENSTACK_TYPE):
Expand All @@ -42,14 +42,14 @@ def create(keystone_client, args, **kwargs):
set_openstack_runtime_properties(ctx, user, USER_OPENSTACK_TYPE)


@operation
@operation(resumable=True)
@with_keystone_client
def delete(keystone_client, **kwargs):
delete_resource_and_runtime_properties(ctx, keystone_client,
RUNTIME_PROPERTIES_KEYS)


@operation
@operation(resumable=True)
@with_keystone_client
def update(keystone_client, args, **kwargs):
user_dict = create_object_dict(ctx, USER_OPENSTACK_TYPE, args, {})
Expand All @@ -58,6 +58,7 @@ def update(keystone_client, args, **kwargs):
set_openstack_runtime_properties(ctx, user, USER_OPENSTACK_TYPE)


@operation(resumable=True)
@with_keystone_client
def list_users(keystone_client, args, **kwargs):
users_list = keystone_client.users.list(**args)
Expand Down
Loading

0 comments on commit 4b70c45

Please sign in to comment.