dfilppi | 9981f55 | 2017-08-07 20:10:53 +0000 | [diff] [blame] | 1 | ######### |
| 2 | # Copyright (c) 2015 GigaSpaces Technologies Ltd. All rights reserved |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # * See the License for the specific language governing permissions and |
| 14 | # * limitations under the License. |
| 15 | |
| 16 | from cloudify import ctx |
| 17 | from cloudify.decorators import operation |
| 18 | from cloudify.exceptions import NonRecoverableError |
| 19 | |
| 20 | from openstack_plugin_common import (with_keystone_client, |
| 21 | with_nova_client, |
| 22 | with_cinder_client, |
| 23 | with_neutron_client, |
| 24 | get_resource_id, |
| 25 | use_external_resource, |
| 26 | delete_resource_and_runtime_properties, |
| 27 | validate_resource, |
| 28 | COMMON_RUNTIME_PROPERTIES_KEYS, |
| 29 | OPENSTACK_ID_PROPERTY, |
| 30 | OPENSTACK_TYPE_PROPERTY, |
| 31 | OPENSTACK_NAME_PROPERTY) |
| 32 | |
| 33 | |
| 34 | PROJECT_OPENSTACK_TYPE = 'project' |
| 35 | |
| 36 | TENANT_QUOTA_TYPE = 'quota' |
| 37 | |
| 38 | RUNTIME_PROPERTIES_KEYS = COMMON_RUNTIME_PROPERTIES_KEYS |
| 39 | |
| 40 | |
| 41 | @operation |
| 42 | @with_keystone_client |
| 43 | def create(keystone_client, **kwargs): |
| 44 | if use_external_resource(ctx, keystone_client, PROJECT_OPENSTACK_TYPE): |
| 45 | return |
| 46 | |
| 47 | project_dict = { |
| 48 | 'name': get_resource_id(ctx, PROJECT_OPENSTACK_TYPE), |
| 49 | 'domain': 'default' |
| 50 | } |
| 51 | |
| 52 | project_dict.update(ctx.node.properties['project']) |
| 53 | project = keystone_client.projects.create(**project_dict) |
| 54 | |
| 55 | ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] = project.id |
| 56 | ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] = \ |
| 57 | PROJECT_OPENSTACK_TYPE |
| 58 | ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = project.name |
| 59 | |
| 60 | |
| 61 | @operation |
| 62 | @with_keystone_client |
| 63 | @with_nova_client |
| 64 | @with_cinder_client |
| 65 | @with_neutron_client |
| 66 | def start(keystone_client, nova_client, cinder_client, neutron_client, |
| 67 | **kwargs): |
| 68 | project_id = ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] |
| 69 | users = ctx.node.properties['users'] |
| 70 | validate_users(users, keystone_client) |
| 71 | |
| 72 | assign_users(project_id, users, keystone_client) |
| 73 | |
| 74 | quota = ctx.node.properties[TENANT_QUOTA_TYPE] |
| 75 | update_quota(project_id, quota, nova_client, 'nova') |
| 76 | update_quota(project_id, quota, neutron_client, 'neutron') |
| 77 | update_quota(project_id, quota, cinder_client, 'cinder') |
| 78 | |
| 79 | |
| 80 | @operation |
| 81 | @with_keystone_client |
| 82 | @with_nova_client |
| 83 | @with_cinder_client |
| 84 | @with_neutron_client |
| 85 | def delete(keystone_client, nova_client, cinder_client, |
| 86 | neutron_client, **kwargs): |
| 87 | tenant_id = ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] |
| 88 | quota = ctx.node.properties[TENANT_QUOTA_TYPE] |
| 89 | delete_quota(tenant_id, quota, nova_client, 'nova') |
| 90 | delete_quota(tenant_id, quota, neutron_client, 'neutron') |
| 91 | delete_quota(tenant_id, quota, cinder_client, 'cinder') |
| 92 | delete_resource_and_runtime_properties(ctx, keystone_client, |
| 93 | RUNTIME_PROPERTIES_KEYS) |
| 94 | |
| 95 | |
| 96 | @operation |
| 97 | @with_keystone_client |
| 98 | def creation_validation(keystone_client, **kwargs): |
| 99 | validate_resource(ctx, keystone_client, PROJECT_OPENSTACK_TYPE) |
| 100 | |
| 101 | |
| 102 | def assign_users(project_id, users, keystone_client): |
| 103 | for user in users: |
| 104 | roles = user['roles'] |
| 105 | u = keystone_client.users.find(name=user['name']) |
| 106 | for role in roles: |
| 107 | r = keystone_client.roles.find(name=role) |
| 108 | keystone_client.roles.grant(user=u.id, |
| 109 | project=project_id, |
| 110 | role=r.id) |
| 111 | |
| 112 | |
| 113 | def validate_users(users, keystone_client): |
| 114 | user_names = [user['name'] for user in users] |
| 115 | if len(user_names) > len(set(user_names)): |
| 116 | raise NonRecoverableError('Users are not unique') |
| 117 | |
| 118 | for user_name in user_names: |
| 119 | keystone_client.users.find(name=user_name) |
| 120 | |
| 121 | for user in users: |
| 122 | if len(user['roles']) > len(set(user['roles'])): |
| 123 | msg = 'Roles for user {} are not unique' |
| 124 | raise NonRecoverableError(msg.format(user['name'])) |
| 125 | |
| 126 | role_names = {role for user in users for role in user['roles']} |
| 127 | for role_name in role_names: |
| 128 | keystone_client.roles.find(name=role_name) |
| 129 | |
| 130 | |
| 131 | def update_quota(tenant_id, quota, client, what_quota): |
| 132 | updated_quota = quota.get(what_quota) |
| 133 | if updated_quota: |
| 134 | if what_quota == 'neutron': |
| 135 | new_quota = client.update_quota(tenant_id=tenant_id, |
| 136 | body={'quota': updated_quota}) |
| 137 | else: |
| 138 | new_quota = client.quotas.update(tenant_id=tenant_id, |
| 139 | **updated_quota) |
| 140 | ctx.logger.info( |
| 141 | 'Updated {0} quota: {1}'.format(what_quota, str(new_quota))) |
| 142 | |
| 143 | |
| 144 | def delete_quota(project_id, quota, client, what_quota): |
| 145 | deleting_quota = quota.get(what_quota) |
| 146 | if deleting_quota: |
| 147 | if what_quota == 'neutron': |
| 148 | client.delete_quota(tenant_id=project_id) |
| 149 | else: |
| 150 | client.quotas.delete(tenant_id=project_id) |