From 2b3cb11e881668e07757368d603a5b978ec6fae6 Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Wed, 18 Dec 2019 09:52:47 +0100 Subject: [PATCH] Retire repository Fuel (from openstack namespace) and fuel-ccp (in x namespace) repositories are unused and ready to retire. This change removes all content from the repository and adds the usual README file to point out that the repository is retired following the process from https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project See also http://lists.openstack.org/pipermail/openstack-discuss/2019-December/011647.html Depends-On: https://review.opendev.org/699362 Change-Id: I1cdc15fbd41ebea088c76729abf6b120165b9ed1 --- .gitignore | 31 - .testr.conf | 5 - MAINTAINERS | 69 -- MANIFEST.in | 1 - README.rst | 44 +- fuelclient/__init__.py | 90 -- fuelclient/cli/__init__.py | 19 - fuelclient/cli/actions/__init__.py | 80 -- fuelclient/cli/actions/base.py | 129 --- fuelclient/cli/actions/deploy.py | 74 -- fuelclient/cli/actions/deployment_tasks.py | 108 -- fuelclient/cli/actions/environment.py | 228 ----- fuelclient/cli/actions/fact.py | 136 --- fuelclient/cli/actions/fuelversion.py | 42 - fuelclient/cli/actions/graph.py | 163 --- fuelclient/cli/actions/health.py | 105 -- fuelclient/cli/actions/interrupt.py | 58 -- fuelclient/cli/actions/network.py | 151 --- fuelclient/cli/actions/network_group.py | 147 --- fuelclient/cli/actions/node.py | 418 -------- fuelclient/cli/actions/nodegroup.py | 137 --- fuelclient/cli/actions/notifications.py | 113 --- fuelclient/cli/actions/openstack_config.py | 155 --- fuelclient/cli/actions/plugins.py | 209 ---- fuelclient/cli/actions/release.py | 172 ---- fuelclient/cli/actions/role.py | 155 --- fuelclient/cli/actions/settings.py | 86 -- fuelclient/cli/actions/snapshot.py | 84 -- fuelclient/cli/actions/token.py | 37 - fuelclient/cli/actions/user.py | 65 -- fuelclient/cli/actions/vip.py | 106 -- fuelclient/cli/arguments.py | 787 --------------- fuelclient/cli/error.py | 155 --- fuelclient/cli/formatting.py | 161 --- fuelclient/cli/parser.py | 246 ----- fuelclient/cli/serializers.py | 152 --- fuelclient/client.py | 248 ----- fuelclient/commands/__init__.py | 0 fuelclient/commands/base.py | 253 ----- fuelclient/commands/environment.py | 933 ------------------ fuelclient/commands/extension.py | 98 -- fuelclient/commands/fuelversion.py | 35 - fuelclient/commands/graph.py | 414 -------- fuelclient/commands/health.py | 177 ---- fuelclient/commands/network_group.py | 174 ---- fuelclient/commands/network_template.py | 103 -- fuelclient/commands/node.py | 609 ------------ fuelclient/commands/openstack_config.py | 182 ---- fuelclient/commands/plugins.py | 117 --- fuelclient/commands/release.py | 146 --- fuelclient/commands/role.py | 268 ----- fuelclient/commands/sequence.py | 203 ---- fuelclient/commands/snapshot.py | 132 --- fuelclient/commands/tag.py | 265 ----- fuelclient/commands/task.py | 309 ------ fuelclient/commands/vip.py | 182 ---- fuelclient/common/__init__.py | 0 fuelclient/common/data_utils.py | 81 -- fuelclient/consts.py | 34 - fuelclient/fuel_client.yaml | 18 - fuelclient/fuelclient_settings.py | 198 ---- fuelclient/hooks.py | 21 - fuelclient/main.py | 81 -- fuelclient/objects/__init__.py | 35 - fuelclient/objects/base.py | 68 -- fuelclient/objects/environment.py | 646 ------------ fuelclient/objects/extension.py | 47 - fuelclient/objects/fuelversion.py | 24 - fuelclient/objects/health.py | 86 -- fuelclient/objects/network_group.py | 108 -- fuelclient/objects/node.py | 206 ---- fuelclient/objects/nodegroup.py | 83 -- fuelclient/objects/notifications.py | 67 -- fuelclient/objects/openstack_config.py | 72 -- fuelclient/objects/plugins.py | 526 ---------- fuelclient/objects/release.py | 53 - fuelclient/objects/role.py | 59 -- fuelclient/objects/sequence.py | 21 - fuelclient/objects/tag.py | 56 -- fuelclient/objects/task.py | 133 --- fuelclient/profiler.py | 99 -- fuelclient/tests/__init__.py | 0 fuelclient/tests/functional/__init__.py | 0 fuelclient/tests/functional/base.py | 218 ---- .../tests/functional/common/__init__.py | 0 fuelclient/tests/functional/v1/__init__.py | 0 fuelclient/tests/functional/v1/test_client.py | 516 ---------- fuelclient/tests/functional/v2/__init__.py | 0 fuelclient/tests/functional/v2/test_client.py | 82 -- fuelclient/tests/unit/__init__.py | 0 fuelclient/tests/unit/common/__init__.py | 0 fuelclient/tests/unit/common/test_config.py | 145 --- .../tests/unit/common/test_environments.py | 127 --- .../unit/common/test_network_template.py | 157 --- fuelclient/tests/unit/common/test_release.py | 88 -- .../tests/unit/common/test_serializers.py | 74 -- fuelclient/tests/unit/common/test_settings.py | 97 -- fuelclient/tests/unit/common/test_utils.py | 331 ------- fuelclient/tests/unit/v1/__init__.py | 0 fuelclient/tests/unit/v1/base.py | 72 -- .../tests/unit/v1/test_attributes_actions.py | 52 - .../tests/unit/v1/test_authentication.py | 105 -- fuelclient/tests/unit/v1/test_base_action.py | 78 -- .../unit/v1/test_deployment_history_action.py | 166 ---- .../unit/v1/test_deployment_tasks_actions.py | 134 --- fuelclient/tests/unit/v1/test_environment.py | 194 ---- fuelclient/tests/unit/v1/test_fuel_version.py | 49 - fuelclient/tests/unit/v1/test_graph_action.py | 261 ----- .../tests/unit/v1/test_network_groups.py | 136 --- .../tests/unit/v1/test_networks_action.py | 81 -- fuelclient/tests/unit/v1/test_nodegroups.py | 145 --- fuelclient/tests/unit/v1/test_nodes.py | 139 --- .../tests/unit/v1/test_nodes_execute_tasks.py | 142 --- .../unit/v1/test_nodes_general_action.py | 42 - .../unit/v1/test_notifications_action.py | 211 ---- .../tests/unit/v1/test_openstack_config.py | 204 ---- fuelclient/tests/unit/v1/test_parser.py | 33 - fuelclient/tests/unit/v1/test_performance.py | 153 --- .../tests/unit/v1/test_plugins_action.py | 209 ---- .../tests/unit/v1/test_plugins_object.py | 485 --------- .../unit/v1/test_release_networks_action.py | 42 - fuelclient/tests/unit/v1/test_roles.py | 175 ---- fuelclient/tests/unit/v1/test_snapshot.py | 109 -- fuelclient/tests/unit/v1/test_token_action.py | 36 - fuelclient/tests/unit/v1/test_user_action.py | 83 -- fuelclient/tests/unit/v1/test_vip_action.py | 214 ---- fuelclient/tests/unit/v2/__init__.py | 0 fuelclient/tests/unit/v2/cli/__init__.py | 0 .../unit/v2/cli/test_deployment_graph.py | 392 -------- fuelclient/tests/unit/v2/cli/test_engine.py | 171 ---- fuelclient/tests/unit/v2/cli/test_env.py | 714 -------------- .../tests/unit/v2/cli/test_extension.py | 79 -- .../tests/unit/v2/cli/test_fuel_version.py | 48 - fuelclient/tests/unit/v2/cli/test_health.py | 169 ---- .../tests/unit/v2/cli/test_network_group.py | 88 -- .../unit/v2/cli/test_network_template.py | 64 -- fuelclient/tests/unit/v2/cli/test_node.py | 625 ------------ .../unit/v2/cli/test_openstack_config.py | 146 --- fuelclient/tests/unit/v2/cli/test_plugins.py | 84 -- fuelclient/tests/unit/v2/cli/test_release.py | 87 -- fuelclient/tests/unit/v2/cli/test_role.py | 359 ------- .../tests/unit/v2/cli/test_sequences.py | 100 -- fuelclient/tests/unit/v2/cli/test_snapshot.py | 131 --- fuelclient/tests/unit/v2/cli/test_tag.py | 367 ------- fuelclient/tests/unit/v2/cli/test_task.py | 261 ----- fuelclient/tests/unit/v2/cli/test_vip.py | 84 -- fuelclient/tests/unit/v2/lib/__init__.py | 0 fuelclient/tests/unit/v2/lib/test_api.py | 43 - fuelclient/tests/unit/v2/lib/test_client.py | 54 - .../unit/v2/lib/test_deployment_graph.py | 377 ------- .../unit/v2/lib/test_deployment_history.py | 126 --- .../tests/unit/v2/lib/test_environment.py | 531 ---------- .../tests/unit/v2/lib/test_extension.py | 83 -- .../tests/unit/v2/lib/test_fuel_version.py | 39 - fuelclient/tests/unit/v2/lib/test_health.py | 292 ------ .../tests/unit/v2/lib/test_network_group.py | 116 --- .../unit/v2/lib/test_network_template.py | 78 -- fuelclient/tests/unit/v2/lib/test_node.py | 561 ----------- .../unit/v2/lib/test_openstack_config.py | 151 --- fuelclient/tests/unit/v2/lib/test_plugins.py | 170 ---- fuelclient/tests/unit/v2/lib/test_release.py | 75 -- fuelclient/tests/unit/v2/lib/test_role.py | 160 --- fuelclient/tests/unit/v2/lib/test_sequence.py | 105 -- fuelclient/tests/unit/v2/lib/test_snapshot.py | 61 -- fuelclient/tests/unit/v2/lib/test_tag.py | 160 --- fuelclient/tests/unit/v2/lib/test_task.py | 101 -- .../unit/v2/lib/test_task_additional_info.py | 58 -- fuelclient/tests/unit/v2/lib/test_vip.py | 74 -- fuelclient/tests/utils/__init__.py | 92 -- .../tests/utils/fake_additional_info.py | 97 -- .../tests/utils/fake_deployment_history.py | 156 --- fuelclient/tests/utils/fake_env.py | 32 - fuelclient/tests/utils/fake_extension.py | 36 - fuelclient/tests/utils/fake_fuel_version.py | 29 - fuelclient/tests/utils/fake_health.py | 70 -- fuelclient/tests/utils/fake_net_conf.py | 52 - fuelclient/tests/utils/fake_network_group.py | 36 - fuelclient/tests/utils/fake_node.py | 135 --- fuelclient/tests/utils/fake_node_group.py | 42 - .../tests/utils/fake_openstack_config.py | 39 - fuelclient/tests/utils/fake_plugin.py | 49 - fuelclient/tests/utils/fake_release.py | 129 --- fuelclient/tests/utils/fake_role.py | 51 - fuelclient/tests/utils/fake_tag.py | 37 - fuelclient/tests/utils/fake_task.py | 35 - fuelclient/tests/utils/random_data.py | 42 - fuelclient/utils.py | 214 ---- fuelclient/v1/__init__.py | 56 -- fuelclient/v1/base_v1.py | 56 -- fuelclient/v1/cluster_settings.py | 31 - fuelclient/v1/deployment_history.py | 117 --- fuelclient/v1/deployment_info.py | 31 - fuelclient/v1/environment.py | 189 ---- fuelclient/v1/extension.py | 37 - fuelclient/v1/fuelversion.py | 32 - fuelclient/v1/graph.py | 296 ------ fuelclient/v1/health.py | 127 --- fuelclient/v1/network_configuration.py | 31 - fuelclient/v1/network_group.py | 50 - fuelclient/v1/node.py | 320 ------ fuelclient/v1/openstack_config.py | 62 -- fuelclient/v1/plugins.py | 76 -- fuelclient/v1/release.py | 37 - fuelclient/v1/role.py | 67 -- fuelclient/v1/sequence.py | 107 -- fuelclient/v1/snapshot.py | 33 - fuelclient/v1/tag.py | 57 -- fuelclient/v1/task.py | 37 - fuelclient/v1/vip.py | 67 -- requirements.txt | 10 - setup.cfg | 152 --- setup.py | 29 - specs/python-fuelclient.spec | 67 -- test-requirements.txt | 17 - tools/env.sh | 49 - tools/env_functions.sh | 78 -- tox.ini | 81 -- 217 files changed, 8 insertions(+), 29321 deletions(-) delete mode 100644 .gitignore delete mode 100644 .testr.conf delete mode 100644 MAINTAINERS delete mode 100644 MANIFEST.in delete mode 100644 fuelclient/__init__.py delete mode 100644 fuelclient/cli/__init__.py delete mode 100644 fuelclient/cli/actions/__init__.py delete mode 100644 fuelclient/cli/actions/base.py delete mode 100644 fuelclient/cli/actions/deploy.py delete mode 100644 fuelclient/cli/actions/deployment_tasks.py delete mode 100644 fuelclient/cli/actions/environment.py delete mode 100644 fuelclient/cli/actions/fact.py delete mode 100644 fuelclient/cli/actions/fuelversion.py delete mode 100644 fuelclient/cli/actions/graph.py delete mode 100644 fuelclient/cli/actions/health.py delete mode 100644 fuelclient/cli/actions/interrupt.py delete mode 100644 fuelclient/cli/actions/network.py delete mode 100644 fuelclient/cli/actions/network_group.py delete mode 100644 fuelclient/cli/actions/node.py delete mode 100644 fuelclient/cli/actions/nodegroup.py delete mode 100644 fuelclient/cli/actions/notifications.py delete mode 100644 fuelclient/cli/actions/openstack_config.py delete mode 100644 fuelclient/cli/actions/plugins.py delete mode 100644 fuelclient/cli/actions/release.py delete mode 100644 fuelclient/cli/actions/role.py delete mode 100644 fuelclient/cli/actions/settings.py delete mode 100644 fuelclient/cli/actions/snapshot.py delete mode 100644 fuelclient/cli/actions/token.py delete mode 100644 fuelclient/cli/actions/user.py delete mode 100644 fuelclient/cli/actions/vip.py delete mode 100644 fuelclient/cli/arguments.py delete mode 100644 fuelclient/cli/error.py delete mode 100644 fuelclient/cli/formatting.py delete mode 100644 fuelclient/cli/parser.py delete mode 100644 fuelclient/cli/serializers.py delete mode 100644 fuelclient/client.py delete mode 100644 fuelclient/commands/__init__.py delete mode 100644 fuelclient/commands/base.py delete mode 100644 fuelclient/commands/environment.py delete mode 100644 fuelclient/commands/extension.py delete mode 100644 fuelclient/commands/fuelversion.py delete mode 100644 fuelclient/commands/graph.py delete mode 100644 fuelclient/commands/health.py delete mode 100644 fuelclient/commands/network_group.py delete mode 100644 fuelclient/commands/network_template.py delete mode 100644 fuelclient/commands/node.py delete mode 100644 fuelclient/commands/openstack_config.py delete mode 100644 fuelclient/commands/plugins.py delete mode 100644 fuelclient/commands/release.py delete mode 100644 fuelclient/commands/role.py delete mode 100644 fuelclient/commands/sequence.py delete mode 100644 fuelclient/commands/snapshot.py delete mode 100644 fuelclient/commands/tag.py delete mode 100644 fuelclient/commands/task.py delete mode 100644 fuelclient/commands/vip.py delete mode 100644 fuelclient/common/__init__.py delete mode 100644 fuelclient/common/data_utils.py delete mode 100644 fuelclient/consts.py delete mode 100644 fuelclient/fuel_client.yaml delete mode 100644 fuelclient/fuelclient_settings.py delete mode 100644 fuelclient/hooks.py delete mode 100644 fuelclient/main.py delete mode 100644 fuelclient/objects/__init__.py delete mode 100644 fuelclient/objects/base.py delete mode 100644 fuelclient/objects/environment.py delete mode 100644 fuelclient/objects/extension.py delete mode 100644 fuelclient/objects/fuelversion.py delete mode 100644 fuelclient/objects/health.py delete mode 100644 fuelclient/objects/network_group.py delete mode 100644 fuelclient/objects/node.py delete mode 100644 fuelclient/objects/nodegroup.py delete mode 100644 fuelclient/objects/notifications.py delete mode 100644 fuelclient/objects/openstack_config.py delete mode 100644 fuelclient/objects/plugins.py delete mode 100644 fuelclient/objects/release.py delete mode 100644 fuelclient/objects/role.py delete mode 100644 fuelclient/objects/sequence.py delete mode 100644 fuelclient/objects/tag.py delete mode 100644 fuelclient/objects/task.py delete mode 100644 fuelclient/profiler.py delete mode 100644 fuelclient/tests/__init__.py delete mode 100644 fuelclient/tests/functional/__init__.py delete mode 100644 fuelclient/tests/functional/base.py delete mode 100644 fuelclient/tests/functional/common/__init__.py delete mode 100644 fuelclient/tests/functional/v1/__init__.py delete mode 100644 fuelclient/tests/functional/v1/test_client.py delete mode 100644 fuelclient/tests/functional/v2/__init__.py delete mode 100644 fuelclient/tests/functional/v2/test_client.py delete mode 100644 fuelclient/tests/unit/__init__.py delete mode 100644 fuelclient/tests/unit/common/__init__.py delete mode 100644 fuelclient/tests/unit/common/test_config.py delete mode 100644 fuelclient/tests/unit/common/test_environments.py delete mode 100644 fuelclient/tests/unit/common/test_network_template.py delete mode 100644 fuelclient/tests/unit/common/test_release.py delete mode 100644 fuelclient/tests/unit/common/test_serializers.py delete mode 100644 fuelclient/tests/unit/common/test_settings.py delete mode 100644 fuelclient/tests/unit/common/test_utils.py delete mode 100644 fuelclient/tests/unit/v1/__init__.py delete mode 100644 fuelclient/tests/unit/v1/base.py delete mode 100644 fuelclient/tests/unit/v1/test_attributes_actions.py delete mode 100644 fuelclient/tests/unit/v1/test_authentication.py delete mode 100644 fuelclient/tests/unit/v1/test_base_action.py delete mode 100644 fuelclient/tests/unit/v1/test_deployment_history_action.py delete mode 100644 fuelclient/tests/unit/v1/test_deployment_tasks_actions.py delete mode 100644 fuelclient/tests/unit/v1/test_environment.py delete mode 100644 fuelclient/tests/unit/v1/test_fuel_version.py delete mode 100644 fuelclient/tests/unit/v1/test_graph_action.py delete mode 100644 fuelclient/tests/unit/v1/test_network_groups.py delete mode 100644 fuelclient/tests/unit/v1/test_networks_action.py delete mode 100644 fuelclient/tests/unit/v1/test_nodegroups.py delete mode 100644 fuelclient/tests/unit/v1/test_nodes.py delete mode 100644 fuelclient/tests/unit/v1/test_nodes_execute_tasks.py delete mode 100644 fuelclient/tests/unit/v1/test_nodes_general_action.py delete mode 100644 fuelclient/tests/unit/v1/test_notifications_action.py delete mode 100644 fuelclient/tests/unit/v1/test_openstack_config.py delete mode 100644 fuelclient/tests/unit/v1/test_parser.py delete mode 100644 fuelclient/tests/unit/v1/test_performance.py delete mode 100644 fuelclient/tests/unit/v1/test_plugins_action.py delete mode 100644 fuelclient/tests/unit/v1/test_plugins_object.py delete mode 100644 fuelclient/tests/unit/v1/test_release_networks_action.py delete mode 100644 fuelclient/tests/unit/v1/test_roles.py delete mode 100644 fuelclient/tests/unit/v1/test_snapshot.py delete mode 100644 fuelclient/tests/unit/v1/test_token_action.py delete mode 100644 fuelclient/tests/unit/v1/test_user_action.py delete mode 100644 fuelclient/tests/unit/v1/test_vip_action.py delete mode 100644 fuelclient/tests/unit/v2/__init__.py delete mode 100644 fuelclient/tests/unit/v2/cli/__init__.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_deployment_graph.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_engine.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_env.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_extension.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_fuel_version.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_health.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_network_group.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_network_template.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_node.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_openstack_config.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_plugins.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_release.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_role.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_sequences.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_snapshot.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_tag.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_task.py delete mode 100644 fuelclient/tests/unit/v2/cli/test_vip.py delete mode 100644 fuelclient/tests/unit/v2/lib/__init__.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_api.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_client.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_deployment_graph.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_deployment_history.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_environment.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_extension.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_fuel_version.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_health.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_network_group.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_network_template.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_node.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_openstack_config.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_plugins.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_release.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_role.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_sequence.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_snapshot.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_tag.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_task.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_task_additional_info.py delete mode 100644 fuelclient/tests/unit/v2/lib/test_vip.py delete mode 100644 fuelclient/tests/utils/__init__.py delete mode 100644 fuelclient/tests/utils/fake_additional_info.py delete mode 100644 fuelclient/tests/utils/fake_deployment_history.py delete mode 100644 fuelclient/tests/utils/fake_env.py delete mode 100644 fuelclient/tests/utils/fake_extension.py delete mode 100644 fuelclient/tests/utils/fake_fuel_version.py delete mode 100644 fuelclient/tests/utils/fake_health.py delete mode 100644 fuelclient/tests/utils/fake_net_conf.py delete mode 100644 fuelclient/tests/utils/fake_network_group.py delete mode 100644 fuelclient/tests/utils/fake_node.py delete mode 100644 fuelclient/tests/utils/fake_node_group.py delete mode 100644 fuelclient/tests/utils/fake_openstack_config.py delete mode 100644 fuelclient/tests/utils/fake_plugin.py delete mode 100644 fuelclient/tests/utils/fake_release.py delete mode 100644 fuelclient/tests/utils/fake_role.py delete mode 100644 fuelclient/tests/utils/fake_tag.py delete mode 100644 fuelclient/tests/utils/fake_task.py delete mode 100644 fuelclient/tests/utils/random_data.py delete mode 100644 fuelclient/utils.py delete mode 100644 fuelclient/v1/__init__.py delete mode 100644 fuelclient/v1/base_v1.py delete mode 100644 fuelclient/v1/cluster_settings.py delete mode 100644 fuelclient/v1/deployment_history.py delete mode 100644 fuelclient/v1/deployment_info.py delete mode 100644 fuelclient/v1/environment.py delete mode 100644 fuelclient/v1/extension.py delete mode 100644 fuelclient/v1/fuelversion.py delete mode 100644 fuelclient/v1/graph.py delete mode 100644 fuelclient/v1/health.py delete mode 100644 fuelclient/v1/network_configuration.py delete mode 100644 fuelclient/v1/network_group.py delete mode 100644 fuelclient/v1/node.py delete mode 100644 fuelclient/v1/openstack_config.py delete mode 100644 fuelclient/v1/plugins.py delete mode 100644 fuelclient/v1/release.py delete mode 100644 fuelclient/v1/role.py delete mode 100644 fuelclient/v1/sequence.py delete mode 100644 fuelclient/v1/snapshot.py delete mode 100644 fuelclient/v1/tag.py delete mode 100644 fuelclient/v1/task.py delete mode 100644 fuelclient/v1/vip.py delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 specs/python-fuelclient.spec delete mode 100644 test-requirements.txt delete mode 100755 tools/env.sh delete mode 100644 tools/env_functions.sh delete mode 100644 tox.ini diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 36878425..00000000 --- a/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -*.pyc -*.sqlite - -*.gem - -# vim swap files -.*.swp - -# services' runtime files -*.log -*.pid - -# Vagrant housekeeping file -.vagrant - -build -dist -lock - -*.egg -.testrepository -.tox -.venv -.idea -.DS_Store -test_run/* - -*.egg-info - -fuelclient-*.xml -.coverage diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index 00e20ade..00000000 --- a/.testr.conf +++ /dev/null @@ -1,5 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 OS_LOG_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ ${OS_TEST_PATH:-./fuelclient/tests/unit} $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list -test_run_concurrency=echo 1 diff --git a/MAINTAINERS b/MAINTAINERS deleted file mode 100644 index c8b884f2..00000000 --- a/MAINTAINERS +++ /dev/null @@ -1,69 +0,0 @@ ---- -description: - For Fuel team structure and contribution policy, see [1]. - - This is repository level MAINTAINERS file. All contributions to this - repository must be approved by one or more Core Reviewers [2]. - If you are contributing to files (or create new directories) in - root folder of this repository, please contact Core Reviewers for - review and merge requests. - - If you are contributing to subfolders of this repository, please - check 'maintainers' section of this file in order to find maintainers - for those specific modules. - - It is mandatory to get +1 from one or more maintainers before asking - Core Reviewers for review/merge in order to decrease a load on Core Reviewers [3]. - Exceptions are when maintainers are actually cores, or when maintainers - are not available for some reason (e.g. on vacation). - - [1] http://specs.openstack.org/openstack/fuel-specs/policy/team-structure.html - [2] https://review.openstack.org/#/admin/groups/551,members - [3] http://lists.openstack.org/pipermail/openstack-dev/2015-August/072406.html - - Please keep this file in YAML format in order to allow helper scripts - to read this as a configuration data. - -maintainers: - -- ./: - - name: Alexander Saprykin - email: asaprykin@mirantis.com - IRC: asaprykin - - - name: Bulat Gaifullin - email: bgaifullin@mirantis.com - IRC: bgaifullin - - - name: Maciej Kwiek - email: mkwiek@mirantis.com - IRC: mkwiek - - - name: Sylwester Brzeczkowski - email: sbrzeczkowski@mirantis.com - IRC: sylwesterB - -- specs/: - - name: Mikhail Ivanov - email: mivanov@mirantis.com - IRC: mivanov - - - name: Artem Silenkov - email: asilenkov@mirantis.com - IRC: asilenkov - - - name: Alexander Tsamutali - email: atsamutali@mirantis.com - IRC: astsmtl - - - name: Daniil Trishkin - email: dtrishkin@mirantis.com - IRC: dtrishkin - - - name: Ivan Udovichenko - email: iudovichenko@mirantis.com - IRC: tlbr - - - name: Igor Yozhikov - email: iyozhikov@mirantis.com - IRC: IgorYozhikov diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 30fa462f..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include fuelclient/fuel_client.yaml diff --git a/README.rst b/README.rst index 59693822..86e34d67 100644 --- a/README.rst +++ b/README.rst @@ -1,38 +1,10 @@ -======================== -Team and repository tags -======================== +This project is no longer maintained. -.. image:: http://governance.openstack.org/badges/python-fuelclient.svg - :target: http://governance.openstack.org/reference/tags/index.html - -.. Change things from this point on - -python-fuelclient -================= - -python-fuelclient provides a CLI tool and a Python API wrapper for interacting -with `Fuel `_. - - ------------------ -Project resources ------------------ - -Project status, bugs, and blueprints are tracked on Launchpad: - https://launchpad.net/fuel - -Development documentation is hosted here: - https://docs.fuel-infra.org/fuel-dev - -User guide can be found here: - http://docs.mirantis.com - -Any additional information can be found on the Fuel's project wiki - https://wiki.openstack.org/wiki/Fuel - -Anyone wishing to contribute to python-fuelclient should follow the general -OpenStack process. A good reference for it can be found here: - https://wiki.openstack.org/wiki/How_To_Contribute - - http://docs.openstack.org/infra/manual/developers.html +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". +For any further questions, please email +openstack-discuss@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/fuelclient/__init__.py b/fuelclient/__init__.py deleted file mode 100644 index d9c92b88..00000000 --- a/fuelclient/__init__.py +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -# DO NOT PUT ANY IMPORTS HERE BECAUSE THIS FILE IS USED -# DURING THE INSTALLATION. - -try: - import pkg_resources - try: - __version__ = pkg_resources.get_distribution( - "python-fuelclient").version - except pkg_resources.DistributionNotFound: - __version__ = "" -except ImportError: - __version__ = "" - - -def connect(host, port, http_proxy=None, os_username=None, os_password=None, - os_tenant_name=None, debug=False): - """Creates API connection.""" - from fuelclient import client - - return client.APIClient( - host, port, http_proxy=http_proxy, os_username=os_username, - os_password=os_password, os_tenant_name=os_tenant_name, debug=debug) - - -def get_client(resource, version='v1', connection=None): - """Gets an API client for a resource - - python-fuelclient provides access to Fuel's API - through a set of per-resource facades. In order to - get a proper facade it's necessary to specify the name - of the API resource and the version of Fuel's API. - - :param resource: Name of the resource to get a facade for. - :type resource: str - Valid values are environment, node and task - :param version: Version of the Fuel's API - :type version: str, - Available: v1. Default: v1. - :param connection: API connection - :type connection: fuelclient.client.APIClient - :return: Facade to the specified resource that wraps - calls to the specified version of the API. - - """ - from fuelclient import v1 - - version_map = { - 'v1': { - 'cluster-settings': v1.cluster_settings, - 'deployment_history': v1.deployment_history, - 'deployment-info': v1.deployment_info, - 'environment': v1.environment, - 'extension': v1.extension, - 'fuel-version': v1.fuelversion, - 'graph': v1.graph, - 'health': v1.health, - 'network-configuration': v1.network_configuration, - 'network-group': v1.network_group, - 'node': v1.node, - 'openstack-config': v1.openstack_config, - 'plugins': v1.plugins, - 'release': v1.release, - 'role': v1.role, - 'sequence': v1.sequence, - 'snapshot': v1.snapshot, - 'task': v1.task, - 'tag': v1.tag, - 'vip': v1.vip - } - } - - try: - return version_map[version][resource].get_client(connection) - except KeyError: - msg = 'Cannot load API client for "{r}" in the API version "{v}".' - raise ValueError(msg.format(r=resource, v=version)) diff --git a/fuelclient/cli/__init__.py b/fuelclient/cli/__init__.py deleted file mode 100644 index 9aa98811..00000000 --- a/fuelclient/cli/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -"""fuelclient.cli sub-module contains functionality of -fuelclient command line interface - - -""" diff --git a/fuelclient/cli/actions/__init__.py b/fuelclient/cli/actions/__init__.py deleted file mode 100644 index 3d82f2c3..00000000 --- a/fuelclient/cli/actions/__init__.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2014 Mirantis, 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. -"""fuelclient.cli.actions sub-module contains files with action classes -which implement command line interface logic - -All action classes must be added to action_tuple to be used by parser -""" -from fuelclient.cli.actions.deploy import DeployChangesAction -from fuelclient.cli.actions.deploy import RedeployChangesAction -from fuelclient.cli.actions.deployment_tasks import DeploymentTasksAction -from fuelclient.cli.actions.environment import EnvironmentAction -from fuelclient.cli.actions.fact import DeploymentAction -from fuelclient.cli.actions.fact import ProvisioningAction -from fuelclient.cli.actions.graph import GraphAction -from fuelclient.cli.actions.token import TokenAction -from fuelclient.cli.actions.health import HealthCheckAction -from fuelclient.cli.actions.interrupt import ResetAction -from fuelclient.cli.actions.interrupt import StopAction -from fuelclient.cli.actions.network import NetworkAction -from fuelclient.cli.actions.network import NetworkTemplateAction -from fuelclient.cli.actions.network_group import NetworkGroupAction -from fuelclient.cli.actions.node import NodeAction -from fuelclient.cli.actions.nodegroup import NodeGroupAction -from fuelclient.cli.actions.notifications import NotificationsAction -from fuelclient.cli.actions.notifications import NotifyAction -from fuelclient.cli.actions.openstack_config import OpenstackConfigAction -from fuelclient.cli.actions.release import ReleaseAction -from fuelclient.cli.actions.role import RoleAction -from fuelclient.cli.actions.settings import SettingsAction -from fuelclient.cli.actions.snapshot import SnapshotAction -from fuelclient.cli.actions.user import UserAction -from fuelclient.cli.actions.plugins import PluginAction -from fuelclient.cli.actions.fuelversion import FuelVersionAction -from fuelclient.cli.actions.vip import VIPAction - -actions_tuple = ( - DeployChangesAction, - DeploymentAction, - DeploymentTasksAction, - EnvironmentAction, - FuelVersionAction, - GraphAction, - HealthCheckAction, - NetworkAction, - NetworkGroupAction, - NetworkTemplateAction, - NodeAction, - NodeGroupAction, - NotificationsAction, - NotifyAction, - OpenstackConfigAction, - PluginAction, - ProvisioningAction, - RedeployChangesAction, - ReleaseAction, - ResetAction, - RoleAction, - SettingsAction, - SnapshotAction, - StopAction, - TokenAction, - UserAction, - VIPAction, -) - -actions = dict( - (action.action_name, action()) - for action in actions_tuple -) diff --git a/fuelclient/cli/actions/base.py b/fuelclient/cli/actions/base.py deleted file mode 100644 index 284e9787..00000000 --- a/fuelclient/cli/actions/base.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from functools import partial -from functools import wraps -import os - -import six - -from fuelclient.cli import error -from fuelclient.cli.formatting import quote_and_join -from fuelclient.cli.serializers import Serializer -from fuelclient.client import DefaultAPIClient - - -class Action(object): - """Action class generalizes logic of action execution - method action_func - entry point of parser with parsed arguments - - flag_func_map - is tuple of pairs ("flag", self.some_method) where - "flag" is name of argument which causes "some_method" to be called. - None is used as "flag" when method will be called without any flag. - - serializer - is Serializer class instance which supposed to be the - only way to read and write to output or file system. - - args - tuple of function calls of functions from arguments module, - is a manifest of all arguments used in action, and is used to initialize - argparse subparser of that action. - """ - def __init__(self): - # Mapping of flags to methods - self.flag_func_map = None - self.serializer = Serializer() - - def action_func(self, params): - """Entry point for all actions subclasses - """ - DefaultAPIClient.debug_mode(debug=params.debug) - - self.serializer = Serializer.from_params(params) - if self.flag_func_map is not None: - for flag, method in self.flag_func_map: - if flag is None or getattr(params, flag): - method(params) - break - - @property - def examples(self): - """examples property is concatenation of __doc__ strings from - methods in child action classes, and is added as epilog of help - output - """ - methods_with_docs = set( - method - for _, method in self.flag_func_map - ) - return "Examples:\n\n" + \ - "\n".join( - six.moves.map( - lambda method: ( - "\t" + method.__doc__.replace("\n ", "\n") - ), - methods_with_docs - ) - ).format( - action_name=self.action_name - ) - - def full_path_directory(self, directory, base_name): - full_path = os.path.join(directory, base_name) - if not os.path.exists(full_path): - try: - os.mkdir(full_path) - except OSError as e: - raise error.ActionException(six.text_type(e)) - return full_path - - def default_directory(self, directory=None): - return os.path.abspath(os.curdir if directory is None else directory) - - -def wrap(method, args, f): - """wrap - is second order function, purpose of which is to - generalize argument checking for methods in actions in form - of decorator with arguments. - - 'check_all' and 'check_any' are partial function of wrap. - """ - @wraps(f) - def wrapped_f(self, params): - if method(getattr(params, _arg) for _arg in args): - return f(self, params) - else: - raise error.ArgumentException( - "{0} required!".format( - quote_and_join( - "--" + arg for arg in args - ) - ) - ) - return wrapped_f - - -def check_all(*args): - """check_all - decorator with arguments, which checks that - all arguments are given before running action method, if - not all arguments are given, it raises an ArgumentException. - """ - return partial(wrap, all, args) - - -def check_any(*args): - """check_any - decorator with arguments, which checks that - at least one arguments is given before running action method, - if no arguments were given, it raises an ArgumentException. - """ - return partial(wrap, any, args) diff --git a/fuelclient/cli/actions/deploy.py b/fuelclient/cli/actions/deploy.py deleted file mode 100644 index f33585d3..00000000 --- a/fuelclient/cli/actions/deploy.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright 2014 Mirantis, 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 six - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.objects.environment import Environment - - -class ChangesAction(Action): - - action_name = None - actions_func_map = {} - - def __init__(self): - super(ChangesAction, self).__init__() - self.args = ( - Args.get_env_arg(required=True), - Args.get_dry_run_deployment_arg(), - ) - self.flag_func_map = ( - (None, self.deploy_changes), - ) - - def print_deploy_info(self, deploy_task): - six.print_("Deployment task with id {t} for the environment {e} " - "has been started.".format(t=deploy_task.id, - e=deploy_task.env.id) - ) - - def deploy_changes(self, params): - """To apply all changes to some environment: - fuel --env 1 {action_name} - """ - env = Environment(params.env) - - deploy_task = getattr( - env, self.actions_func_map[self.action_name])( - dry_run=params.dry_run) - self.serializer.print_to_output( - deploy_task.data, - deploy_task, - print_method=self.print_deploy_info) - - -class DeployChangesAction(ChangesAction): - """Deploy changes to environments - """ - action_name = "deploy-changes" - - def __init__(self): - super(DeployChangesAction, self).__init__() - self.actions_func_map[self.action_name] = 'deploy_changes' - - -class RedeployChangesAction(ChangesAction): - """Redeploy changes to environment which is in the operational state - """ - action_name = "redeploy-changes" - - def __init__(self): - super(RedeployChangesAction, self).__init__() - self.actions_func_map[self.action_name] = 'redeploy_changes' diff --git a/fuelclient/cli/actions/deployment_tasks.py b/fuelclient/cli/actions/deployment_tasks.py deleted file mode 100644 index 9dabb66d..00000000 --- a/fuelclient/cli/actions/deployment_tasks.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.formatting import format_table - -from fuelclient.v1.deployment_history import DeploymentHistoryClient - - -class DeploymentTasksAction(Action): - """Show deployment tasks - """ - action_name = "deployment-tasks" - - def __init__(self): - super(DeploymentTasksAction, self).__init__() - self.args = [ - group( - Args.get_list_arg("List all deployment tasks"), - ), - Args.get_single_task_arg(required=True), - Args.get_deployment_node_arg( - "Node ids." - ), - Args.get_status_arg( - "Statuses: pending, error, ready, running, skipped" - ), - Args.get_tasks_names_arg( - "Show deployment history for specific deployment tasks names " - "and group output by task" - ), - Args.get_show_parameters_arg( - "Show deployment tasks parameters" - ), - Args.get_include_summary_arg( - "Show deployment tasks summary" - ), - ] - self.flag_func_map = ( - (None, self.list), - ) - - def list(self, params): - """To display all deployment tasks for task: - fuel deployment-tasks --task-id 5 - - To display deployment tasks for some nodes: - fuel deployment-tasks --task-id 5 --node 1,2 - - To display deployment tasks for some statuses(pending, error, - ready, running): - fuel deployment-tasks --task-id 5 --status pending,running - - To display deployment tasks for some statuses(pending, error, - ready, running) on some nodes: - fuel deployment-tasks --task-id 5 --status error --node 1,2 - - To display certain deployment tasks results only: - fuel deployment-tasks --task-id 5 - --task-name task-name1,task-name2 - - To display tasks parameters use: - fuel deployment-tasks --task-id 5 --show-parameters - - """ - client = DeploymentHistoryClient() - tasks_names = getattr(params, 'task-name', None) - show_parameters = getattr(params, 'show-parameters') - statuses = params.status.split(',') if params.status else [] - nodes = params.node.split(',') if params.node else [] - tasks_names = tasks_names.split(',') if tasks_names else [] - include_summary = getattr(params, 'include-summary') - - data = client.get_all( - transaction_id=params.task, - nodes=nodes, - statuses=statuses, - tasks_names=tasks_names, - show_parameters=show_parameters, - include_summary=include_summary - ) - - if show_parameters: - table_keys = client.tasks_records_keys - else: - table_keys = client.history_records_keys - if include_summary: - table_keys += ('summary',) - self.serializer.print_to_output( - data, - format_table( - data, - acceptable_keys=table_keys - ) - ) diff --git a/fuelclient/cli/actions/environment.py b/fuelclient/cli/actions/environment.py deleted file mode 100644 index 549b591f..00000000 --- a/fuelclient/cli/actions/environment.py +++ /dev/null @@ -1,228 +0,0 @@ -# Copyright 2014 Mirantis, 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 sys - -import six - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -from fuelclient.cli.actions.base import check_any -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.formatting import format_table -from fuelclient.objects.environment import Environment - - -class EnvironmentAction(Action): - """Create, list and modify currently existing environments(clusters) - """ - action_name = "environment" - - def __init__(self): - super(EnvironmentAction, self).__init__() - self.args = [ - Args.get_env_arg(), - group( - Args.get_list_arg( - "List all available environments" - ), - Args.get_set_arg( - "Set environment parameters e.g., its name" - ), - Args.get_delete_arg( - "Delete environment with a specific id or name" - ), - Args.get_create_arg( - "Create a new environment with " - "specific release id and name" - ), - ), - Args.get_release_arg( - "Release id" - ), - Args.get_force_arg( - "Do it anyway" - ), - Args.get_name_arg( - "Environment name" - ), - Args.get_nst_arg( - "Set network segment type" - ), - Args.get_deployment_tasks_arg("Environment tasks configuration"), - Args.get_attributes_arg("Environment attributes"), - group( - Args.get_download_arg( - "Download configuration of specific cluster"), - Args.get_upload_arg( - "Upload configuration to specific cluster") - ), - Args.get_dir_arg( - "Select directory to which download release attributes"), - ] - self.flag_func_map = ( - ("deployment-tasks", self.deployment_tasks), - ("attributes", self.attributes), - ("create", self.create), - ("set", self.set), - ("delete", self.delete), - (None, self.list) - ) - - @check_all("name", "release") - def create(self, params): - """To create an environment with name MyEnv and release id=1 run: - fuel env create --name MyEnv --rel 1 - - By default, it creates environment setting neutron with VLAN - network segmentation as network provider - To specify other modes add optional arguments: - fuel env create --name MyEnv --rel 1 --net-segment-type vlan - """ - - if params.nst == 'gre': - six.print_( - "WARNING: GRE network segmentation type is deprecated " - "since 7.0 release.", file=sys.stderr) - - env = Environment.create( - params.name, - params.release, - params.nst, - ) - - data = env.get_fresh_data() - - self.serializer.print_to_output( - data, - u"Environment '{name}' with id={id} was created!" - .format(**data) - ) - - @check_all("env") - def set(self, params): - """To change environment name: - fuel --env 1 env set --name NewEnvName - """ - acceptable_params = ('name', ) - - env = Environment(params.env, params=params) - - # forming message for output and data structure for request body - # TODO(aroma): make it less ugly - msg_template = ("Following attributes are changed for " - "the environment: {env_attributes}") - - env_attributes = [] - update_kwargs = dict() - for param_name in acceptable_params: - attr_value = getattr(params, param_name, None) - if attr_value: - update_kwargs[param_name] = attr_value - env_attributes.append( - ''.join([param_name, '=', str(attr_value)]) - ) - - data = env.set(update_kwargs) - env_attributes = ', '.join(env_attributes) - self.serializer.print_to_output( - data, - msg_template.format(env_attributes=env_attributes) - ) - - @check_all("env") - def delete(self, params): - """To delete the environment: - fuel --env 1 env --force delete - """ - env = Environment(params.env, params=params) - - if env.status == "operational" and not params.force: - self.serializer.print_to_output(env.data, - "Deleting an operational" - "environment is a dangerous " - "operation. Please use --force to " - "bypass this message.") - return - - data = env.delete() - self.serializer.print_to_output( - data, - "Environment with id={0} was deleted" - .format(env.id) - ) - - def list(self, params): - """Print all available environments: - fuel env - """ - acceptable_keys = ("id", "status", "name", "release_id", ) - data = Environment.get_all_data() - if params.env: - data = filter( - lambda x: x[u"id"] == int(params.env), - data - ) - self.serializer.print_to_output( - data, - format_table( - data, - acceptable_keys=acceptable_keys - ) - ) - - @check_all("env") - @check_any("download", "upload") - def deployment_tasks(self, params): - """Modify deployment_tasks for environment: - fuel env --env 1 --deployment-tasks --download - fuel env --env 1 --deployment-tasks --upload - """ - cluster = Environment(params.env) - dir_path = self.full_path_directory( - params.dir, 'cluster_{0}'.format(params.env)) - full_path = '{0}/deployment_tasks'.format(dir_path) - if params.download: - tasks = cluster.get_deployment_tasks() - self.serializer.write_to_path(full_path, tasks) - print("Deployment tasks for cluster {0} " - "downloaded into {1}.yaml.".format(cluster.id, full_path)) - elif params.upload: - tasks = self.serializer.read_from_file(full_path) - cluster.update_deployment_tasks(tasks) - print("Deployment tasks for cluster {0} " - "uploaded from {1}.yaml".format(cluster.id, full_path)) - - @check_all("env") - @check_any("download", "upload") - def attributes(self, params): - """Modify attributes of the environment: - fuel env --env 1 --attributes --download - fuel env --env 1 --attributes --upload - """ - cluster = Environment(params.env) - dir_path = self.full_path_directory( - params.dir, 'cluster_{0}'.format(params.env)) - full_path = '{0}/attributes'.format(dir_path) - - if params.download: - attributes = cluster.get_attributes() - self.serializer.write_to_path(full_path, attributes) - print("Attributes of cluster {0} " - "downloaded into {1}.yaml.".format(cluster.id, full_path)) - elif params.upload: - attributes = self.serializer.read_from_file(full_path) - cluster.update_attributes(attributes, params.force) - print("Attributes of cluster {0} " - "uploaded from {1}.yaml".format(cluster.id, full_path)) diff --git a/fuelclient/cli/actions/fact.py b/fuelclient/cli/actions/fact.py deleted file mode 100644 index 22ea41ea..00000000 --- a/fuelclient/cli/actions/fact.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.objects.environment import Environment - - -class FactAction(Action): - - action_name = None - - def __init__(self): - super(FactAction, self).__init__() - self.args = [ - Args.get_env_arg(required=True), - group( - Args.get_delete_arg( - "Delete current {0} data.".format(self.action_name) - ), - Args.get_download_arg( - "Download current {0} data.".format(self.action_name) - ), - Args.get_upload_arg( - "Upload current {0} data.".format(self.action_name) - ), - Args.get_default_arg( - "Download default {0} data.".format(self.action_name) - ), - required=True - ), - Args.get_dir_arg( - "Directory with {0} data.".format(self.action_name) - ), - Args.get_node_arg( - "Node ids." - ), - Args.get_not_split_facts_args(), - ] - self.flag_func_map = ( - ("default", self.default), - ("upload", self.upload), - ("delete", self.delete), - ("download", self.download) - ) - - def default(self, params): - """To get default {action_name} information for some environment: - fuel --env 1 {action_name} --default - - It's possible to get default {action_name} information - just for some nodes: - fuel --env 1 {action_name} --default --node 1,2,3 - """ - env = Environment(params.env) - dir_name = env.write_facts_to_dir( - self.action_name, - env.get_default_facts( - self.action_name, nodes=params.node, split=params.split - ), - directory=params.dir, - serializer=self.serializer - ) - print( - "Default {0} info was downloaded to {1}".format( - self.action_name, - dir_name - ) - ) - - def upload(self, params): - """To upload {action_name} information for some environment: - fuel --env 1 {action_name} --upload - """ - env = Environment(params.env) - facts = env.read_fact_info( - self.action_name, - directory=params.dir, - serializer=self.serializer - ) - env.upload_facts(self.action_name, facts) - print("{0} facts were uploaded.".format(self.action_name)) - - def delete(self, params): - """Also {action_name} information can be left or - taken from specific directory: - fuel --env 1 {action_name} --upload \\ - --dir path/to/some/directory - """ - env = Environment(params.env) - env.delete_facts(self.action_name) - print("{0} facts deleted.".format(self.action_name)) - - def download(self, params): - """To download {action_name} information for some environment: - fuel --env 1 {action_name} --download - """ - env = Environment(params.env) - dir_name = env.write_facts_to_dir( - self.action_name, - env.get_facts( - self.action_name, nodes=params.node, split=params.split - ), - directory=params.dir, - serializer=self.serializer - ) - print( - "Current {0} info was downloaded to {1}".format( - self.action_name, - dir_name - ) - ) - - -class DeploymentAction(FactAction): - """Show computed deployment facts for orchestrator - """ - action_name = "deployment" - - -class ProvisioningAction(FactAction): - """Show computed provisioning facts for orchestrator - """ - action_name = "provisioning" diff --git a/fuelclient/cli/actions/fuelversion.py b/fuelclient/cli/actions/fuelversion.py deleted file mode 100644 index bc9d0511..00000000 --- a/fuelclient/cli/actions/fuelversion.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2015 Mirantis, 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 fuelclient.cli.arguments as Args - -from fuelclient.cli.actions.base import Action -from fuelclient.objects.fuelversion import FuelVersion - - -class FuelVersionAction(Action): - """Show Fuel server's version - """ - - action_name = "fuel-version" - - def __init__(self): - super(FuelVersionAction, self).__init__() - - self.args = [ - Args.get_list_arg("Show fuel version"), - ] - self.flag_func_map = ( - (None, self.version), - ) - - def version(self, params): - """To show fuel version data: - fuel fuel-version - """ - version = FuelVersion.get_all_data() - print(self.serializer.serialize(version)) diff --git a/fuelclient/cli/actions/graph.py b/fuelclient/cli/actions/graph.py deleted file mode 100644 index 3197144e..00000000 --- a/fuelclient/cli/actions/graph.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 -import sys - -import six - -from fuelclient.cli.actions import base -import fuelclient.cli.arguments as Args -from fuelclient.cli import error -from fuelclient.objects import environment - - -class GraphAction(base.Action): - """Manipulate deployment graph's representation.""" - - action_name = 'graph' - - task_types = ('skipped', 'group', 'stage') - - def __init__(self): - super(GraphAction, self).__init__() - self.args = ( - Args.get_env_arg(), - Args.get_render_arg( - "Render graph from DOT to PNG" - ), - Args.get_download_arg( - "Download graph of specific cluster" - ), - Args.get_dir_arg( - "Select target dir to render graph." - ), - Args.group( - Args.get_skip_tasks(), - Args.get_tasks() - ), - Args.get_graph_endpoint(), - Args.get_graph_startpoint(), - Args.get_remove_type_arg(self.task_types), - Args.get_parents_arg(), - Args.get_tred_arg("Apply transitive reduction filter for graph."), - ) - self.flag_func_map = ( - ('render', self.render), - ('download', self.download), - ) - - @base.check_all("env") - def download(self, params): - """Download deployment graph to stdout - - fuel graph --env 1 --download - fuel graph --env 1 --download --tasks A B C - fuel graph --env 1 --download --skip X Y --end pre_deployment - fuel graph --env 1 --download --skip X Y --start post_deployment - - Specify output: - fuel graph --env 1 --download > output/dir/file.gv - - Get parents only for task A: - - fuel graph --env 1 --download --parents-for A - """ - env = environment.Environment(params.env) - - parents_for = getattr(params, 'parents-for') - - used_params = "# params:\n" - for param in ('start', 'end', 'skip', 'tasks', 'parents-for', - 'remove'): - used_params += "# - {0}: {1}\n".format(param, - getattr(params, param)) - - tasks = params.tasks - - if not tasks or (params.skip or params.end or params.start): - tasks = env.get_tasks( - skip=params.skip, end=params.end, - start=params.start, include=params.tasks) - - dotraph = env.get_deployment_tasks_graph(tasks, - parents_for=parents_for, - remove=params.remove) - sys.stdout.write(six.text_type(used_params)) - sys.stdout.write(six.text_type(dotraph)) - - @base.check_all("render") - def render(self, params): - """Render graph in PNG format - - fuel graph --render graph.gv - fuel graph --render graph.gv --dir ./output/dir/ - - To apply transitive reduction filter on rendered graph: - - fuel graph --render graph.gv --tred - fuel graph --render graph.gv --dir ./output/dir/ --tred - - Read graph from stdin - some_process | fuel graph --render - - """ - if params.render == '-': - dot_data = sys.stdin.read() - out_filename = 'graph.gv' - elif not os.path.exists(params.render): - raise error.ArgumentException( - "Input file does not exist" - ) - else: - out_filename = os.path.basename(params.render) - with open(params.render, 'r') as f: - dot_data = f.read() - - target_dir = self.full_path_directory( - self.default_directory(params.dir), - '' - ) - target_file = os.path.join( - target_dir, - '{0}.png'.format(out_filename), - ) - - if not os.access(os.path.dirname(target_file), os.W_OK): - raise error.ActionException( - 'Path {0} is not writable'.format(target_file)) - render_graph(dot_data, target_file, params.tred) - print('Graph saved in "{0}"'.format(target_file)) - - -def render_graph(input_data, output_path, tred=False): - """Renders DOT graph using pygraphviz. - - :param input_data: DOT graph representation - :param output_path: path to the rendered graph - :param tred: applies transitive reduction of graph - """ - try: - import pygraphviz - except ImportError: - raise error.WrongEnvironmentError( - "This action requires Graphviz installed " - "together with 'pygraphviz' Python library") - - graph = pygraphviz.AGraph(string=input_data) - if tred: - graph = graph.tred() - - graph.draw(output_path, prog='dot', format='png') diff --git a/fuelclient/cli/actions/health.py b/fuelclient/cli/actions/health.py deleted file mode 100644 index 8ceddad6..00000000 --- a/fuelclient/cli/actions/health.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 2014 Mirantis, 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 sys - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.error import EnvironmentException -from fuelclient.cli.formatting import format_table -from fuelclient.cli.formatting import print_health_check -from fuelclient.objects.environment import Environment -import six - - -class HealthCheckAction(Action): - """Run health check on environment - """ - action_name = "health" - - _allowed_statuses = ( - 'error', - 'operational', - 'update_error', - ) - - def __init__(self): - super(HealthCheckAction, self).__init__() - self.args = ( - Args.get_env_arg(required=True), - Args.get_list_arg("List all available checks"), - Args.get_force_arg("Forced test run"), - Args.get_check_arg("Run check for some testset."), - Args.get_ostf_username_arg(), - Args.get_ostf_password_arg(), - Args.get_ostf_tenant_name_arg() - ) - - self.flag_func_map = ( - ("check", self.check), - (None, self.list) - ) - - def check(self, params): - """To run some health checks: - fuel --env 1 health --check smoke,sanity - """ - env = Environment(params.env) - - if env.status not in self._allowed_statuses and not params.force: - raise EnvironmentException( - "Environment is not ready to run health check " - "because it is in {0} state. " - "Health check is likely to fail because of " - "this. Use --force flag to proceed anyway.". format(env.status) - ) - - if env.is_customized and not params.force: - raise EnvironmentException( - "Environment deployment facts were updated. " - "Health check is likely to fail because of " - "that. Use --force flag to proceed anyway." - ) - test_sets_to_check = params.check or set( - ts["id"] for ts in env.get_testsets()) - ostf_credentials = {} - if params.ostf_tenant_name is not None: - ostf_credentials['tenant'] = params.ostf_tenant_name - if params.ostf_username is not None: - ostf_credentials['username'] = params.ostf_username - if params.ostf_password is not None: - ostf_credentials['password'] = params.ostf_password - if not ostf_credentials: - six.print_("WARNING: ostf credentials are going to be", - "mandatory in the next release.", file=sys.stderr) - env.run_test_sets(test_sets_to_check, ostf_credentials) - tests_state = env.get_state_of_tests() - self.serializer.print_to_output( - tests_state, - env, - print_method=print_health_check - ) - - def list(self, params): - """To list all health check test sets: - fuel --env 1 health - or: - fuel --env 1 health --list - """ - env = Environment(params.env) - test_sets = env.get_testsets() - self.serializer.print_to_output( - test_sets, - format_table(test_sets) - ) diff --git a/fuelclient/cli/actions/interrupt.py b/fuelclient/cli/actions/interrupt.py deleted file mode 100644 index 91ad9f5c..00000000 --- a/fuelclient/cli/actions/interrupt.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2014 Mirantis, 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. - - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.objects.environment import Environment - - -class InterruptAction(Action): - - def __init__(self): - super(InterruptAction, self).__init__() - self.args = [ - Args.get_env_arg(required=True) - ] - self.flag_func_map = ( - (None, self.interrupt), - ) - - def interrupt(self, params): - """To {action_name} some environment: - fuel --env 1 {action_name} - """ - env = Environment(params.env) - intercept_task = getattr(env, self.action_name)() - self.serializer.print_to_output( - intercept_task.data, - "{0} task of environment with id={1} started. " - "To check task status run 'fuel task --tid {2}'.".format( - self.action_name.title(), - params.env, - intercept_task.data["id"] - ) - ) - - -class StopAction(InterruptAction): - """Stop deployment process for specific environment - """ - action_name = "stop" - - -class ResetAction(InterruptAction): - """Reset deployed process for specific environment - """ - action_name = "reset" diff --git a/fuelclient/cli/actions/network.py b/fuelclient/cli/actions/network.py deleted file mode 100644 index ce454314..00000000 --- a/fuelclient/cli/actions/network.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.objects.environment import Environment - - -class NetworkAction(Action): - """Show or modify network settings of specific environments - """ - action_name = "network" - - def __init__(self): - super(NetworkAction, self).__init__() - self.args = ( - Args.get_env_arg(required=True), - Args.get_dir_arg("Directory with network data."), - group( - Args.get_download_arg( - "Download current network configuration."), - Args.get_verify_arg( - "Verify current network configuration."), - Args.get_upload_arg( - "Upload changed network configuration."), - required=True - ) - ) - self.flag_func_map = ( - ("upload", self.upload), - ("verify", self.verify), - ("download", self.download) - ) - - def upload(self, params): - """To upload network configuration from some - directory for some environment: - fuel --env 1 network --upload --dir path/to/directory - """ - env = Environment(params.env) - network_data = env.read_network_data( - directory=params.dir, - serializer=self.serializer - ) - env.set_network_data(network_data) - print("Network configuration uploaded.") - - def verify(self, params): - """To verify network configuration from some directory - for some environment: - fuel --env 1 network --verify --dir path/to/directory - """ - env = Environment(params.env) - response = env.verify_network() - print( - "Verification status is '{status}'. message: {message}" - .format(**response) - ) - - def download(self, params): - """To download network configuration in this - directory for some environment: - fuel --env 1 network --download - """ - env = Environment(params.env) - network_data = env.get_network_data() - network_file_path = env.write_network_data( - network_data, - directory=params.dir, - serializer=self.serializer) - print( - "Network configuration for environment with id={0}" - " downloaded to {1}" - .format(env.id, network_file_path) - ) - - -class NetworkTemplateAction(Action): - """Manipulate network templates for a specific environment - """ - action_name = 'network-template' - - def __init__(self): - super(NetworkTemplateAction, self).__init__() - self.args = ( - Args.get_env_arg(required=True), - Args.get_dir_arg("Directory with network templates."), - group( - Args.get_download_arg( - "Download current network template configuration."), - Args.get_upload_arg( - "Upload changed network template configuration."), - Args.get_delete_arg( - "Delete network template configuration."), - required=True)) - - self.flag_func_map = ( - ("upload", self.upload), - ("download", self.download), - ("delete", self.delete)) - - def upload(self, params): - """Uploads network template from filesystem path - for specified environment: - fuel --env 1 network-template --upload --dir path/to/directory - """ - env = Environment(params.env) - network_template_data = env.read_network_template_data( - directory=params.dir, - serializer=self.serializer) - env.set_network_template_data(network_template_data) - full_path = self.serializer.prepare_path( - env.get_network_template_data_path(directory=params.dir)) - print("Network template {0} has been uploaded.".format(full_path)) - - def download(self, params): - """Downloads network template in current - directory for specified environment: - fuel --env 1 network-template --download - """ - env = Environment(params.env) - template_data = env.get_network_template_data() - network_template_file_path = env.write_network_template_data( - template_data, - directory=params.dir, - serializer=self.serializer) - - print("Network template configuration for environment with id={0}" - " downloaded to {1}".format(env.id, network_template_file_path)) - - def delete(self, params): - """Deletes network template for specified environment: - fuel --env 1 --network-template --delete - """ - env = Environment(params.env) - env.delete_network_template_data() - - print("Network template configuration for environment id={0}" - " has been deleted.".format(env.id)) diff --git a/fuelclient/cli/actions/network_group.py b/fuelclient/cli/actions/network_group.py deleted file mode 100644 index 524c8657..00000000 --- a/fuelclient/cli/actions/network_group.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright 2015 Mirantis, 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 sys - -import six - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.formatting import format_table -from fuelclient.commands.network_group import get_args_for_update -from fuelclient.objects.network_group import NetworkGroup -from fuelclient.objects.network_group import NetworkGroupCollection - - -class NetworkGroupAction(Action): - """Show or modify network groups - """ - action_name = "network-group" - acceptable_keys = ("id", "name", "vlan_start", "cidr", - "gateway", "group_id") - - def __init__(self): - super(NetworkGroupAction, self).__init__() - self.args = ( - Args.get_env_arg(), - Args.get_name_arg("Name of new network group."), - Args.get_node_group_arg("ID of node group."), - Args.get_release_arg("Release ID this network group belongs to."), - Args.get_vlan_arg("VLAN of network."), - Args.get_cidr_arg("CIDR of network."), - Args.get_gateway_arg("Gateway of network."), - Args.get_network_group_arg("ID of network group."), - Args.get_meta_arg("Metadata in JSON format to override default " - "network metadata."), - group( - Args.get_create_network_arg( - "Create a new network group for the specified " - " node group." - ), - Args.get_delete_arg("Delete specified network groups."), - Args.get_list_arg("List all network groups."), - Args.get_set_arg("Set network group parameters.") - ) - ) - self.flag_func_map = ( - ("create", self.create), - ("delete", self.delete), - ("set", self.set), - (None, self.list), - ) - - @check_all('nodegroup', 'name', 'cidr') - def create(self, params): - """Create a new network group - fuel network-group --create --node-group 1 --name "new network" - --release 2 --vlan 100 --cidr 10.0.0.0/24 - - fuel network-group --create --node-group 2 --name "new network" - --release 2 --vlan 100 --cidr 10.0.0.0/24 --gateway 10.0.0.1 - --meta 'meta information in JSON format' - """ - meta = self.serializer.deserialize(params.meta) if params.meta else {} - - NetworkGroup.create( - params.name, - params.release, - params.vlan, - params.cidr, - params.gateway, - int(params.nodegroup.pop()), - meta - ) - self.serializer.print_to_output( - {}, - "Network group {0} has been created".format(params.name) - ) - - @check_all('network') - def delete(self, params): - """Delete the specified network groups - fuel network-group --delete --network 1 - fuel network-group --delete --network 2,3,4 - """ - ngs = NetworkGroup.get_by_ids(params.network) - for network_group in ngs: - network_group.delete() - - self.serializer.print_to_output( - {}, - "Network groups with IDS {0} have been deleted.".format( - ','.join(params.network)) - ) - - @check_all('network') - def set(self, params): - """Set parameters for the specified network group: - fuel network-group --set --network 1 --name new_name - """ - # Since network has set type and we cannot update multiple network - # groups at once, we pick first network group id from set. - ng_id = next(iter(params.network)) - - if len(params.network) > 1: - msg = ("Warning: Only first network with id={0}" - " will be updated.".format(ng_id)) - six.print_(msg, file=sys.stderr) - - ng = NetworkGroup(ng_id) - - update_params = get_args_for_update(params, self.serializer) - data = ng.set(update_params) - - self.serializer.print_to_output( - data, - "Network group id={0} has been updated".format(ng_id)) - - def list(self, params): - """To list all available network groups: - fuel network-group list - - To filter them by node group: - fuel network-group --node-group 1 - """ - group_collection = NetworkGroupCollection.get_all() - if params.nodegroup: - group_collection.filter_by_group_id(int(params.nodegroup.pop())) - self.serializer.print_to_output( - group_collection.data, - format_table( - group_collection.data, - acceptable_keys=self.acceptable_keys, - ) - ) diff --git a/fuelclient/cli/actions/node.py b/fuelclient/cli/actions/node.py deleted file mode 100644 index c3dd0b76..00000000 --- a/fuelclient/cli/actions/node.py +++ /dev/null @@ -1,418 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from itertools import groupby -from operator import attrgetter - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -from fuelclient.cli.actions.base import check_any -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli import error -from fuelclient.cli.formatting import format_table -from fuelclient.objects.environment import Environment -from fuelclient.objects.node import Node -from fuelclient.objects.node import NodeCollection - - -class NodeAction(Action): - """List and assign available nodes to environments - """ - action_name = "node" - acceptable_keys = ("id", "status", "name", "cluster", "ip", - "mac", "roles", "pending_roles", "online", "group_id") - - def __init__(self): - super(NodeAction, self).__init__() - self.args = [ - Args.get_env_arg(), - group( - Args.get_list_arg("List all nodes."), - Args.get_set_arg("Set role for specific node."), - Args.get_delete_arg("Delete specific node from environment."), - Args.get_attributes_arg("Node attributes."), - Args.get_network_arg("Node network configuration."), - Args.get_disk_arg("Node disk configuration."), - Args.get_deploy_arg("Deploy specific nodes."), - Args.get_hostname_arg("Set node hostname."), - Args.get_node_name_arg("Set node name."), - Args.get_delete_from_db_arg( - "Delete specific nodes only from fuel db.\n" - "User should still delete node from cobbler"), - Args.get_provision_arg("Provision specific nodes."), - ), - group( - Args.get_default_arg( - "Get default configuration of some node"), - Args.get_download_arg( - "Download configuration of specific node"), - Args.get_upload_arg( - "Upload configuration to specific node") - ), - Args.get_dir_arg( - "Select directory to which download node attributes"), - Args.get_node_arg("Node id."), - Args.get_force_arg("Bypassing parameter validation."), - Args.get_noop_run_deployment_arg(), - Args.get_all_arg("Select all nodes."), - Args.get_role_arg("Role to assign for node."), - group( - Args.get_skip_tasks(), - Args.get_tasks() - ), - Args.get_graph_endpoint(), - Args.get_graph_startpoint(), - ] - - self.flag_func_map = ( - ("set", self.set), - ("delete", self.delete), - ("network", self.attributes), - ("disk", self.attributes), - ("deploy", self.start), - ("provision", self.start), - ("hostname", self.set_hostname), - ("name", self.set_name), - ("delete-from-db", self.delete_from_db), - ("tasks", self.execute_tasks), - ("skip", self.execute_tasks), - ("end", self.execute_tasks), - ("start", self.execute_tasks), - ("attributes", self.node_attributes), - (None, self.list) - ) - - @check_all("node", "role", "env") - def set(self, params): - """Assign some nodes to environment with with specific roles: - fuel --env 1 node set --node 1 --role controller - fuel --env 1 node set --node 2,3,4 --role compute,cinder - """ - env = Environment(params.env) - nodes = Node.get_by_ids(params.node) - roles = map(str.lower, params.role) - env.assign(nodes, roles) - self.serializer.print_to_output( - {}, - "Nodes {0} with roles {1} " - "were added to environment {2}" - .format(params.node, roles, params.env) - ) - - @check_any("node", "env") - def delete(self, params): - """Remove some nodes from environment: - fuel --env 1 node remove --node 2,3 - - Remove nodes no matter to which environment they were assigned: - fuel node remove --node 2,3,6,7 - - Remove all nodes from some environment: - fuel --env 1 node remove --all - """ - if params.env: - env = Environment(params.env) - if params.node: - env.unassign(params.node) - self.serializer.print_to_output( - {}, - "Nodes with ids {0} were removed " - "from environment with id {1}." - .format(params.node, params.env)) - else: - if params.all: - env.unassign_all() - else: - raise error.ArgumentException( - "You have to select which nodes to remove " - "with --node-id. Try --all for removing all nodes." - ) - self.serializer.print_to_output( - {}, - "All nodes from environment with id {0} were removed." - .format(params.env)) - else: - nodes = map(Node, params.node) - for env_id, _nodes in groupby(nodes, attrgetter("env_id")): - list_of_nodes = [n.id for n in _nodes] - if env_id: - Environment(env_id).unassign(list_of_nodes) - self.serializer.print_to_output( - {}, - "Nodes with ids {0} were removed " - "from environment with id {1}." - .format(list_of_nodes, env_id) - ) - else: - self.serializer.print_to_output( - {}, - "Nodes with ids {0} aren't added to " - "any environment.".format(list_of_nodes) - ) - - @check_all("node") - @check_any("default", "download", "upload") - def attributes(self, params): - """Download current or default disk, network, - configuration for some node: - fuel node --node-id 2 --disk --default - fuel node --node-id 2 --network --download \\ - --dir path/to/directory - - Upload disk, network, configuration for some node: - fuel node --node-id 2 --network --upload - fuel node --node-id 2 --disk --upload --dir path/to/directory - """ - nodes = Node.get_by_ids(params.node) - attribute_type = "interfaces" if params.network else "disks" - attributes = [] - files = [] - if params.default: - for node in nodes: - default_attribute = node.get_default_attribute(attribute_type) - file_path = node.write_attribute( - attribute_type, - default_attribute, - params.dir, - serializer=self.serializer - ) - files.append(file_path) - attributes.append(default_attribute) - message = "Default node attributes for {0} were written" \ - " to:\n{1}".format(attribute_type, "\n".join(files)) - elif params.upload: - for node in nodes: - attribute = node.read_attribute( - attribute_type, - params.dir, - serializer=self.serializer - ) - node.upload_node_attribute( - attribute_type, - attribute - ) - attributes.append(attribute) - message = "Node attributes for {0} were uploaded" \ - " from {1}".format(attribute_type, params.dir) - else: - for node in nodes: - downloaded_attribute = node.get_attribute(attribute_type) - file_path = node.write_attribute( - attribute_type, - downloaded_attribute, - params.dir, - serializer=self.serializer - ) - attributes.append(downloaded_attribute) - files.append(file_path) - message = "Node attributes for {0} were written" \ - " to:\n{1}".format(attribute_type, "\n".join(files)) - print(message) - - def get_env_id(self, node_collection): - env_ids = set(n.env_id for n in node_collection) - if len(env_ids) != 1: - raise error.ActionException( - "Inputed nodes assigned to multiple environments!") - else: - return env_ids.pop() - - @check_all("node") - def start(self, params): - """Deploy/Provision some node: - fuel node --node-id 2 --provision - fuel node --node-id 2 --deploy - """ - node_collection = NodeCollection.init_with_ids(params.node) - method_type = "deploy" if params.deploy else "provision" - env_id_to_start = self.get_env_id(node_collection) - - if not env_id_to_start: - raise error.ActionException( - "Input nodes are not assigned to any environment!") - - task = Environment(env_id_to_start).install_selected_nodes( - method_type, node_collection.collection) - - self.serializer.print_to_output( - task.data, - "Started {0}ing {1}." - .format(method_type, node_collection)) - - @check_all("node") - def execute_tasks(self, params): - """Execute deployment tasks - fuel node --node 2 --tasks hiera netconfig - fuel node --node 2 --tasks netconfig --force - fuel node --node 2 --skip hiera netconfig - fuel node --node 2 --skip rsync --end pre_deployment_end - fuel node --node 2 --end netconfig - fuel node --node 2 --start hiera --end neutron - fuel node --node 2 --start post_deployment_start - """ - node_collection = NodeCollection.init_with_ids(params.node) - env_id_to_start = self.get_env_id(node_collection) - - env = Environment(env_id_to_start) - - tasks = params.tasks or None - force = params.force or None - noop_run = params.noop_run or None - - if params.skip or params.end or params.start: - tasks = env.get_tasks( - skip=params.skip, - end=params.end, - start=params.start, - include=tasks) - - if not tasks: - self.serializer.print_to_output({}, "Nothing to run.") - return - - task = env.execute_tasks( - node_collection.collection, tasks=tasks, force=force, - noop_run=noop_run) - - self.serializer.print_to_output( - task.data, - "Started tasks {0} for nodes {1}.".format(tasks, node_collection)) - - def list(self, params): - """To list all available nodes: - fuel node - - To filter them by environment: - fuel --env-id 1 node - - It's Possible to manipulate nodes with their short mac addresses: - fuel node --node-id 80:ac - fuel node remove --node-id 80:ac,5d:a2 - """ - if params.node: - node_collection = NodeCollection.init_with_ids(params.node) - else: - node_collection = NodeCollection.get_all() - if params.env: - node_collection.filter_by_env_id(int(params.env)) - self.serializer.print_to_output( - node_collection.data, - format_table( - node_collection.data, - acceptable_keys=self.acceptable_keys, - column_to_join=("roles", "pending_roles") - ) - ) - - @check_all("node") - def delete_from_db(self, params): - """To delete nodes from fuel db: - fuel node --node-id 1 --delete-from-db - fuel node --node-id 1 2 --delete-from-db - (this works only for offline nodes) - fuel node --node-id 1 --delete-from-db --force - (this forces deletion of nodes regardless of their state) - """ - if not params.force: - node_collection = NodeCollection.init_with_ids(params.node) - - online_nodes = [node for node in node_collection.data - if node['online']] - - if online_nodes: - raise error.ActionException( - "Nodes with ids {0} cannot be deleted from cluster " - "because they are online. You might want to use the " - "--force option.".format( - [node['id'] for node in online_nodes])) - - NodeCollection.delete_by_ids(params.node) - - self.serializer.print_to_output( - {}, - "Nodes with ids {0} have been deleted from Fuel db.".format( - params.node) - ) - - @staticmethod - def _get_one_node(params): - """Ensures that only one node was passed in the command and returns it. - - :raises ArgumentException: When more than 1 node provided. - """ - if len(params.node) > 1: - raise error.ArgumentException( - "You should select only one node to change.") - - return Node(params.node[0]) - - @check_all("node", "name") - def set_name(self, params): - """To set node name: - fuel node --node-id 1 --name NewName - """ - node = self._get_one_node(params) - node.set({"name": params.name}) - self.serializer.print_to_output( - {}, - u"Name for node with id {0} has been changed to {1}." - .format(node.id, params.name) - ) - - @check_all("node", "hostname") - def set_hostname(self, params): - """To set node hostname: - fuel node --node-id 1 --hostname ctrl-01 - """ - node = self._get_one_node(params) - node.set({"hostname": params.hostname}) - self.serializer.print_to_output( - {}, - "Hostname for node with id {0} has been changed to {1}." - .format(node.id, params.hostname) - ) - - @check_all("node") - @check_any("upload", "download") - def node_attributes(self, params): - """Download node attributes for specified node: - fuel node --node-id 1 --attributes --download [--dir download-dir] - - Upload node attributes for specified node - fuel node --node-id 1 --attributes --upload [--dir upload-dir] - - """ - node = self._get_one_node(params) - if params.upload: - data = node.read_attribute( - 'attributes', params.dir, serializer=self.serializer) - node.update_node_attributes(data) - self.serializer.print_to_output( - {}, - "Attributes for node {0} were uploaded." - .format(node.id)) - elif params.download: - attributes = node.get_node_attributes() - file_path = node.write_attribute( - 'attributes', attributes, - params.dir, serializer=self.serializer) - self.serializer.print_to_output( - {}, - "Attributes for node {0} were written to {1}" - .format(node.id, file_path)) - - else: - raise error.ArgumentException( - "--upload or --download action should be specified.") diff --git a/fuelclient/cli/actions/nodegroup.py b/fuelclient/cli/actions/nodegroup.py deleted file mode 100644 index d30f6d48..00000000 --- a/fuelclient/cli/actions/nodegroup.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2014 Mirantis, 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 sys - -import six - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.error import ActionException -from fuelclient.cli.formatting import format_table -from fuelclient.objects import Environment -from fuelclient.objects.nodegroup import NodeGroup -from fuelclient.objects.nodegroup import NodeGroupCollection - - -class NodeGroupAction(Action): - """Show or modify node groups - """ - action_name = "nodegroup" - acceptable_keys = ("id", "cluster_id", "name") - - def __init__(self): - super(NodeGroupAction, self).__init__() - self.args = ( - Args.get_env_arg(), - Args.get_list_arg("List all node groups."), - Args.get_name_arg("Name of new node group."), - Args.get_group_arg("ID of node group."), - Args.get_node_arg("List of nodes to assign specified group to."), - group( - Args.get_create_arg( - "Create a new node group in the specified environment." - ), - Args.get_assign_arg( - "Assign nodes to the specified node group."), - Args.get_delete_arg( - "Delete specified node groups."), - ) - ) - self.flag_func_map = ( - ("create", self.create), - ("delete", self.delete), - ("assign", self.assign), - (None, self.list) - ) - - @check_all("env", "name") - def create(self, params): - """Create a new node group - fuel --env 1 nodegroup --create --name "group 1" - """ - env_id = int(params.env) - data = NodeGroup.create(params.name, env_id) - env = Environment(env_id) - network_data = env.get_network_data() - seg_type = network_data['networking_parameters'].get( - 'segmentation_type' - ) - if seg_type == 'vlan': - six.print_("WARNING: In VLAN segmentation type, there will be no " - "connectivity over private network between instances " - "running on hypervisors in different segments and that " - "it's a user's responsibility to handle this " - "situation.", - file=sys.stderr) - - self.serializer.print_to_output( - data, - u"Node group '{name}' with id={id} " - u"in environment {env} was created!" - .format(env=env_id, **data) - ) - - @check_all("group") - def delete(self, params): - """Delete the specified node groups - fuel nodegroup --delete --group 1 - fuel nodegroup --delete --group 2,3,4 - """ - ngs = NodeGroup.get_by_ids(params.group) - for n in ngs: - if n.name == "default": - raise ActionException( - "Default node groups cannot be deleted." - ) - data = NodeGroup.delete(n.id) - self.serializer.print_to_output( - data, - u"Node group with id={id} was deleted!" - .format(id=n.id) - ) - - @check_all("node", "group") - def assign(self, params): - """Assign nodes to specified node group: - fuel nodegroup --assign --node 1 --group 1 - fuel nodegroup --assign --node 2,3,4 --group 1 - """ - if len(params.group) > 1: - raise ActionException( - "Nodes can only be assigned to one node group." - ) - - group = NodeGroup(params.group.pop()) - group.assign(params.node) - - def list(self, params): - """To list all available node groups: - fuel nodegroup - - To filter them by environment: - fuel --env-id 1 nodegroup - """ - group_collection = NodeGroupCollection.get_all() - if params.env: - group_collection.filter_by_env_id(int(params.env)) - self.serializer.print_to_output( - group_collection.data, - format_table( - group_collection.data, - acceptable_keys=self.acceptable_keys, - ) - ) diff --git a/fuelclient/cli/actions/notifications.py b/fuelclient/cli/actions/notifications.py deleted file mode 100644 index 0acaee7b..00000000 --- a/fuelclient/cli/actions/notifications.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.formatting import format_table -from fuelclient.objects.notifications import Notifications - - -class NotificationsAction(Action): - """List and create notifications - """ - action_name = "notifications" - - acceptable_keys = ( - "id", - "message", - "status", - "topic", - ) - - def __init__(self): - super(NotificationsAction, self).__init__() - self.args = [ - Args.group( - Args.get_list_arg("List all available notifications."), - Args.get_notify_send_arg("Send notification"), - Args.get_notify_mark_as_read_arg( - "Mark notification(s) as read ('*' to mark all as read)."), - ), - Args.group( - Args.get_notify_topic_arg("Notification topic (severity)"), - ), - Args.get_notify_all_messages_arg( - "Select all messages (only unread by default)."), - ] - self.flag_func_map = ( - ("send", self.send), - ("mark-as-read", self.mark_as_read), - (None, self.list), - ) - - def list(self, params): - """Print all available notifications: - fuel notifications - fuel notifications --list - """ - notifications = Notifications.get_all_data() - - if not params.all: - notifications = [notification for notification in notifications - if notification['status'] == 'unread'] - - self.serializer.print_to_output( - notifications, - format_table( - notifications, - acceptable_keys=self.acceptable_keys - ) - ) - - def mark_as_read(self, params): - """Mark given notifications as read. - fuel notifications --mark-as-read 1 2 - fuel notifications -r 1 2 - """ - result = Notifications.mark_as_read( - ids=getattr(params, 'mark-as-read')) - - self.serializer.print_to_output( - result, - 'Notification(s) marked as read' - ) - - def send(self, params): - """Send notification: - fuel notifications --send "message" --topic done - """ - message = params.send - if isinstance(message, list): - message = ' '.join(message) - result = Notifications.send(message, topic=params.topic) - self.serializer.print_to_output( - result, - "Notification sent") - - -class NotifyAction(NotificationsAction): - """Shortcut for quickly sending a notification. - """ - - action_name = "notify" - - def __init__(self): - super(NotifyAction, self).__init__() - self.args = [ - Args.get_notify_message_arg("Notification message"), - Args.get_notify_topic_arg("Notification topic (severity)"), - ] - self.flag_func_map = ( - (None, self.send), - ) diff --git a/fuelclient/cli/actions/openstack_config.py b/fuelclient/cli/actions/openstack_config.py deleted file mode 100644 index ab85a876..00000000 --- a/fuelclient/cli/actions/openstack_config.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.formatting import format_table -from fuelclient.objects.openstack_config import OpenstackConfig - - -class OpenstackConfigAction(Action): - """Manage openstack configuration""" - - action_name = 'openstack-config' - acceptable_keys = ('id', 'is_active', 'config_type', - 'cluster_id', 'node_id', 'node_role') - - def __init__(self): - super(OpenstackConfigAction, self).__init__() - self.args = ( - Args.get_env_arg(), - Args.get_file_arg("Openstack configuration file"), - Args.get_node_arg("Node IDs list"), - Args.get_single_role_arg("Node role"), - Args.get_config_id_arg("Openstack config ID"), - Args.get_deleted_arg("Get deleted configurations"), - Args.get_force_arg("Force configuration update"), - group( - Args.get_list_arg("List openstack configurations"), - Args.get_download_arg( - "Download current openstack configuration"), - Args.get_upload_arg("Upload new openstack configuration"), - Args.get_delete_arg("Delete openstack configuration"), - Args.get_execute_arg("Apply openstack configuration"), - required=True, - ) - ) - - self.flag_func_map = ( - ('list', self.list), - ('download', self.download), - ('upload', self.upload), - ('delete', self.delete), - ('execute', self.execute) - ) - - @check_all('env') - def list(self, params): - """List all available configurations: - fuel openstack-config --list --env 1 - fuel openstack-config --list --env 1 --node 1[,2,3,...] - fuel openstack-config --list --env 1 --deleted - """ - filters = {'cluster_id': params.env} - - if 'deleted' in params: - filters['is_active'] = int(not params.deleted) - - if 'node' in params: - filters['node_ids'] = params.node - - if 'role' in params: - filters['node_role'] = params.role - - configs = OpenstackConfig.get_filtered_data(**filters) - - self.serializer.print_to_output( - configs, - format_table( - configs, - acceptable_keys=self.acceptable_keys - ) - ) - - @check_all('config-id', 'file') - def download(self, params): - """Download an existing configuration to file: - fuel openstack-config --download --config-id 1 --file config.yaml - """ - config_id = getattr(params, 'config-id') - config = OpenstackConfig(config_id) - data = config.data - OpenstackConfig.write_file(params.file, { - 'configuration': data['configuration']}) - - @check_all('env', 'file') - def upload(self, params): - """Upload new configuration from file: - fuel openstack-config --upload --env 1 --file config.yaml - fuel openstack-config --upload --env 1 --node 1[,2,3,...] - --file config.yaml - fuel openstack-config --upload --env 1 - --role controller --file config.yaml - """ - node_ids = getattr(params, 'node', None) - node_role = getattr(params, 'role', None) - data = OpenstackConfig.read_file(params.file) - - configs = OpenstackConfig.create( - cluster_id=params.env, - configuration=data['configuration'], - node_ids=node_ids, node_role=node_role) - configs = [c.data for c in configs] - self.serializer.print_to_output( - configs, - format_table( - configs, - acceptable_keys=self.acceptable_keys - ) - ) - - @check_all('config-id') - def delete(self, params): - """Delete an existing configuration: - fuel openstack-config --delete --config 1 - """ - config_id = getattr(params, 'config-id') - config = OpenstackConfig(config_id) - config.delete() - print("Openstack configuration '{0}' " - "has been deleted.".format(config_id)) - - @check_all('env') - def execute(self, params): - """Deploy configuration: - fuel openstack-config --execute --env 1 - fuel openstack-config --execute --env 1 --node 1[,2,3,...] - fuel openstack-config --execute --env 1 --role controller - fuel openstack-config --execute --env 1 --force - """ - node_ids = getattr(params, 'node', None) - node_role = getattr(params, 'role', None) - force = getattr(params, 'force', False) - task_result = OpenstackConfig.execute( - cluster_id=params.env, node_ids=node_ids, - node_role=node_role, force=force) - if task_result['status'] == 'error': - print( - 'Error applying openstack configuration: {0}.'.format( - task_result['message']) - ) - else: - print('Openstack configuration update is started.') diff --git a/fuelclient/cli/actions/plugins.py b/fuelclient/cli/actions/plugins.py deleted file mode 100644 index ab9620e8..00000000 --- a/fuelclient/cli/actions/plugins.py +++ /dev/null @@ -1,209 +0,0 @@ -# Copyright 2014 Mirantis, 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 collections -import six - -import fuelclient.cli.arguments as Args - -from fuelclient.cli.actions.base import Action -from fuelclient.cli import error -from fuelclient.cli.formatting import format_table -from fuelclient.objects.plugins import Plugins -from fuelclient import utils - - -class PluginAction(Action): - """List and modify currently available releases - """ - action_name = "plugins" - - acceptable_keys = ( - "id", - "name", - "version", - "package_version", - "releases" - ) - - def __init__(self): - super(PluginAction, self).__init__() - self.args = [ - Args.group( - Args.get_list_arg( - "List of all registered plugins."), - Args.get_plugin_install_arg( - "Install and register plugin package"), - Args.get_plugin_remove_arg( - "Remove and unregister plugin"), - Args.get_plugin_register_arg( - "Register installed plugin"), - Args.get_plugin_unregister_arg( - "Unregister plugin"), - Args.get_plugin_update_arg( - "Update installed plugin"), - Args.get_plugin_downgrade_arg( - "Downgrade installed plugin"), - Args.get_plugin_sync_arg( - "Synchronise plugins with API service")), - Args.get_plugin_arg("Plugin id."), - Args.get_force_arg("Force action") - ] - self.flag_func_map = ( - ("install", self.install), - ("remove", self.remove), - ("update", self.update), - ("downgrade", self.downgrade), - ("sync", self.sync), - ("register", self.register), - ("unregister", self.unregister), - (None, self.list), - ) - - def list(self, params): - """Print all available plugins - - fuel plugins - fuel plugins --list - """ - plugins = Plugins.get_all_data() - # Replace original nested 'release' dictionary (from plugins meta - # dictionary) to flat one with necessary release info (os, version) - for plugin in plugins: - releases = collections.defaultdict(list) - for key in plugin['releases']: - releases[key['os']].append(key['version']) - plugin['releases'] = ', '.join('{} ({})'.format(k, ', '.join(v)) - for k, v in six.iteritems(releases)) - self.serializer.print_to_output( - plugins, - format_table(plugins, acceptable_keys=self.acceptable_keys)) - - def install(self, params): - """Install plugin archive and register in API service - - fuel plugins --install plugin-name-2.0-2.0.1-0.noarch.rpm - """ - file_path = params.install - self.check_file(file_path) - results = Plugins.install(file_path, force=params.force) - self.serializer.print_to_output( - results, - "Plugin {0} was successfully installed.".format( - params.install)) - - def remove(self, params): - """Remove plugin from file system and from API service - - fuel plugins --remove plugin-name==1.0.1 - """ - name, version = self.parse_name_version(params.remove) - results = Plugins.remove(name, version) - - self.serializer.print_to_output( - results, - "Plugin {0} was successfully removed.".format(params.remove)) - - def update(self, params): - """Update plugin from one minor version to another. - For example if there is a plugin with version 2.0.0, - plugin with version 2.0.1 can be used as update. But - plugin with version 2.1.0, cannot be used to update - plugin. Note that update is supported for plugins - beginning from package_version 2.0.0 - - fuel plugins --update plugin-name-2.0-2.0.1-0.noarch.rpm - """ - plugin_path = params.update - self.check_file(plugin_path) - result = Plugins.update(plugin_path) - self.serializer.print_to_output( - result, - "Plugin {0} was successfully updated.".format(plugin_path)) - - def downgrade(self, params): - """Downgrade plugin from one minor version to another. - For example if there is a plugin with version 2.0.1, - plugin with version 2.0.0 can be used to perform downgrade. - Plugin with version 1.0.0, cannot be used to perform downgrade - plugin. Note that downgrade is supported for plugins - beginning from package_version 2.0.0 - - fuel plugins --downgrade plugin-name-2.0-2.0.1-0.noarch.rpm - """ - plugin_path = params.downgrade - self.check_file(plugin_path) - result = Plugins.downgrade(plugin_path) - self.serializer.print_to_output( - result, - "Plugin {0} was successfully downgraded.".format(plugin_path)) - - def sync(self, params): - """Synchronise plugins on file system with plugins in - API service, creates plugin if it is not exists, - updates existent plugins - - fuel plugins --sync - fuel plugins --sync --plugin-id=1,2 - """ - Plugins.sync(plugin_ids=params.plugin) - self.serializer.print_to_output( - None, "Plugins were successfully synchronized.") - - def register(self, params): - """Register plugin in API service - - fuel plugins --register plugin-name==1.0.1 - """ - name, version = self.parse_name_version(params.register) - result = Plugins.register(name, version, force=params.force) - self.serializer.print_to_output( - result, - "Plugin {0} was successfully registered.".format(params.register)) - - def unregister(self, params): - """Deletes plugin from API service - - fuel plugins --unregister plugin-name==1.0.1 - """ - name, version = self.parse_name_version(params.unregister) - result = Plugins.unregister(name, version) - self.serializer.print_to_output( - result, - "Plugin {0} was successfully unregistered." - "".format(params.unregister)) - - def parse_name_version(self, param): - """Takes the string and returns name and version - - :param str param: string with name and version - :raises: error.ArgumentException if version is not specified - """ - attrs = param.split('==') - - if len(attrs) != 2: - raise error.ArgumentException( - 'Syntax: fuel plugins fuel_plugin==1.0.0') - - return attrs - - def check_file(self, file_path): - """Checks if file exists - - :param str file_path: path to the file - :raises: error.ArgumentException if file does not exist - """ - if not utils.file_exists(file_path): - raise error.ArgumentException( - 'File "{0}" does not exists'.format(file_path)) diff --git a/fuelclient/cli/actions/release.py b/fuelclient/cli/actions/release.py deleted file mode 100644 index f43ca103..00000000 --- a/fuelclient/cli/actions/release.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from collections import defaultdict -import os - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -from fuelclient.cli.actions.base import check_any -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.formatting import format_table -from fuelclient.objects.release import Release -from fuelclient import utils - - -class ReleaseAction(Action): - """List and modify currently available releases - """ - action_name = "release" - - def __init__(self): - super(ReleaseAction, self).__init__() - self.args = [ - Args.get_release_arg('Specify particular release id'), - Args.get_list_arg("List all available releases."), - Args.get_network_arg("Release network configuration."), - Args.get_deployment_tasks_arg("Release tasks configuration."), - Args.get_sync_deployment_tasks_arg(), - Args.get_file_pattern_arg(), - Args.get_dir_arg( - "Select directory to which download release attributes"), - group( - Args.get_download_arg( - "Download configuration of specific release"), - Args.get_upload_arg( - "Upload configuration to specific release") - ) - ] - self.flag_func_map = ( - ('sync-deployment-tasks', self.sync_deployment_tasks), - ('deployment-tasks', self.deployment_tasks), - ('network', self.network), - (None, self.list), - ) - - def list(self, params): - """Print all available releases: - fuel release --list - - Print release with specific id=1: - fuel release --rel 1 - """ - acceptable_keys = ( - "id", - "name", - "state", - "operating_system", - "version" - ) - if params.release: - release = Release(params.release) - data = [release.get_fresh_data()] - else: - data = Release.get_all_data() - self.serializer.print_to_output( - data, - format_table( - data, - acceptable_keys=acceptable_keys - ) - ) - - @check_all("release") - @check_any("download", "upload") - def network(self, params): - """Modify release networks configuration. - fuel rel --rel 1 --network --download - fuel rel --rel 2 --network --upload - """ - release = Release(params.release) - dir_path = self.full_path_directory( - params.dir, 'release_{0}'.format(params.release)) - full_path = '{0}/networks'.format(dir_path) - if params.download: - networks = release.get_networks() - self.serializer.write_to_path(full_path, networks) - print("Networks for release {0} " - "downloaded into {1}.yaml".format(release.id, full_path)) - elif params.upload: - networks = self.serializer.read_from_file(full_path) - release.update_networks(networks) - print("Networks for release {0} uploaded from {1}.yaml".format( - release.id, full_path)) - - @check_all("release") - @check_any("download", "upload") - def deployment_tasks(self, params): - """Modify deployment_tasks for release. - fuel rel --rel 1 --deployment-tasks --download - fuel rel --rel 1 --deployment-tasks --upload - """ - release = Release(params.release) - dir_path = self.full_path_directory( - params.dir, 'release_{0}'.format(params.release)) - full_path = '{0}/deployment_tasks'.format(dir_path) - if params.download: - tasks = release.get_deployment_tasks() - self.serializer.write_to_path(full_path, tasks) - print("Deployment tasks for release {0} " - "downloaded into {1}.yaml.".format(release.id, full_path)) - elif params.upload: - tasks = self.serializer.read_from_file(full_path) - release.update_deployment_tasks(tasks) - print("Deployment tasks for release {0}" - " uploaded from {1}.yaml".format(release.id, dir_path)) - - @check_all("dir") - def sync_deployment_tasks(self, params): - """Upload tasks for different releases based on directories. - The string identifier for the release(s) to update is expected to be - found in the path (see `fuel release`), like: - - /etc/puppet// - /etc/puppet/liberty-9.0 - - fuel rel --sync-deployment-tasks --dir /etc/puppet/liberty-9.0/ - fuel rel --sync-deployment-tasks --fp '*tasks.yaml' - - In case no directory was provided: - - fuel rel --sync-deployment-tasks - - The current directory will be used - """ - all_rels = Release.get_all_data() - real_path = os.path.realpath(params.dir) - serialized_tasks = defaultdict(list) - versions = set([r['version'] for r in all_rels]) - - for file_name in utils.iterfiles(real_path, params.filepattern): - for version in versions: - if version in file_name: - serialized_tasks[version].extend( - self.serializer.read_from_full_path(file_name)) - - for rel in all_rels: - release = Release(rel['id']) - data = serialized_tasks.get(rel['version']) - if data: - release.update_deployment_tasks(data) - print("Deployment tasks synchronized for release" - " {0} of version {1}".format(rel['name'], - rel['version'])) - else: - print("No tasks were synchronized for release {0} " - "of version {1}.(Hint: nothing matched " - "{2}/{1}/{3})".format(rel['name'], - rel['version'], - real_path, - params.filepattern)) diff --git a/fuelclient/cli/actions/role.py b/fuelclient/cli/actions/role.py deleted file mode 100644 index a8fd644a..00000000 --- a/fuelclient/cli/actions/role.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2014 Mirantis, 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. - - -from fuelclient.cli.actions.base import Action -from fuelclient.cli.actions.base import check_all -from fuelclient.cli.actions.base import check_any -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.cli.formatting import format_table -from fuelclient.cli.serializers import FileFormatBasedSerializer -from fuelclient.objects.role import Role - - -class RoleAction(Action): - """List all roles for specific release or cluster - """ - action_name = "role" - - fields_mapper = ( - ('env', 'clusters'), - ('release', 'releases') - ) - - def __init__(self): - # NOTE(dshulyak) this serializers are really messed up - # it gets overwritten in several places - self.file_serializer = FileFormatBasedSerializer() - self.args = [ - Args.get_list_arg("List all roles"), - group( - Args.get_env_arg(), - Args.get_release_arg("Release id"), - required=True - ), - Args.get_str_arg("role", help="Name of the role"), - Args.get_file_arg("File with role description"), - - group( - Args.get_create_arg("Create role from file"), - Args.get_boolean_arg("update", help="Update role from file"), - Args.get_delete_arg("Delete role from fuel") - ) - ] - self.flag_func_map = ( - ("delete", self.delete), - ("create", self.create), - ("update", self.update), - ("role", self.item), - (None, self.list), - ) - - def parse_model(self, args): - for param, role_class in self.fields_mapper: - model_id = getattr(args, param) - if model_id: - return role_class, model_id - - @check_any('release', 'env') - def list(self, params): - """Print all available roles for release or cluster - - fuel role --rel 1 - fuel role --env 1 - """ - model, model_id = self.parse_model(params) - roles = Role(owner_type=model, owner_id=model_id).get_all() - - acceptable_keys = ("name", ) - - self.serializer.print_to_output( - roles, - format_table( - roles, - acceptable_keys=acceptable_keys - ) - ) - - @check_all('role', 'file') - @check_any('release', 'env') - def item(self, params): - """Save full role description to file - fuel role --rel 1 --role controller --file some.yaml - fuel role --env 1 --role controller --file some.yaml - """ - model, model_id = self.parse_model(params) - role = Role(owner_type=model, owner_id=model_id).get_role(params.role) - self.file_serializer.write_to_file(params.file, role) - self.file_serializer.print_to_output( - role, - "Role {0} for {1} successfully saved to {2}.".format( - params.role, - model, - params.file)) - - @check_all('file') - @check_any('release', 'env') - def create(self, params): - """Create a role from file description - fuel role --rel 1 --create --file some.yaml - fuel role --env 1 --create --file some.yaml - """ - model, model_id = self.parse_model(params) - role = self.file_serializer.read_from_file(params.file) - role = Role(owner_type=model, owner_id=model_id).create_role(role) - self.file_serializer.print_to_output( - role, - "Role {0} for {1} successfully created from {2}.".format( - role['name'], model, params.file)) - - @check_all('file') - @check_any('release', 'env') - def update(self, params): - """Update a role from file description - fuel role --rel 1 --create --file some.yaml - fuel role --env 1 --create --file some.yaml - """ - model, model_id = self.parse_model(params) - role = self.file_serializer.read_from_file(params.file) - role = Role(owner_type=model, owner_id=model_id).update_role( - role['name'], - role) - self.file_serializer.print_to_output( - role, - "Role {0} for {1} successfully updated from {2}.".format( - params.role, - model, - params.file)) - - @check_all('role') - @check_any('release', 'env') - def delete(self, params): - """Delete role from fuel - fuel role --delete --role controller --rel 1 - fuel role --delete --role controller --env 1 - """ - model, model_id = self.parse_model(params) - Role(owner_type=model, owner_id=model_id).delete_role(params.role) - self.file_serializer.print_to_output( - {}, - "Role {0} for {1} with id {2} successfully deleted.".format( - params.role, - model, - model_id)) diff --git a/fuelclient/cli/actions/settings.py b/fuelclient/cli/actions/settings.py deleted file mode 100644 index 14227687..00000000 --- a/fuelclient/cli/actions/settings.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.arguments import group -from fuelclient.objects.environment import Environment - - -class SettingsAction(Action): - """Show or modify environment settings - """ - action_name = "settings" - - def __init__(self): - super(SettingsAction, self).__init__() - self.args = ( - Args.get_env_arg(required=True), - group( - Args.get_download_arg("Modify current configuration."), - Args.get_default_arg("Open default configuration."), - Args.get_upload_arg("Save current changes in configuration."), - required=True - ), - Args.get_dir_arg("Directory with configuration data."), - Args.get_force_arg("Force settings upload.") - ) - self.flag_func_map = ( - ("upload", self.upload), - ("default", self.default), - ("download", self.download) - ) - - def upload(self, params): - """To upload settings for some environment from some directory: - fuel --env 1 settings --upload --dir path/to/directory - """ - env = Environment(params.env) - settings_data = env.read_settings_data( - directory=params.dir, - serializer=self.serializer - ) - env.set_settings_data(settings_data, params.force) - print("Settings configuration uploaded.") - - def default(self, params): - """To download default settings for some environment in some directory: - fuel --env 1 settings --default --dir path/to/directory - """ - env = Environment(params.env) - default_data = env.get_default_settings_data() - settings_file_path = env.write_settings_data( - default_data, - directory=params.dir, - serializer=self.serializer) - print( - "Default settings configuration downloaded to {0}." - .format(settings_file_path) - ) - - def download(self, params): - """To download settings for some environment in this directory: - fuel --env 1 settings --download - """ - env = Environment(params.env) - settings_data = env.get_settings_data() - settings_file_path = env.write_settings_data( - settings_data, - directory=params.dir, - serializer=self.serializer) - print( - "Settings configuration for environment with id={0}" - " downloaded to {1}" - .format(env.id, settings_file_path) - ) diff --git a/fuelclient/cli/actions/snapshot.py b/fuelclient/cli/actions/snapshot.py deleted file mode 100644 index 68eda198..00000000 --- a/fuelclient/cli/actions/snapshot.py +++ /dev/null @@ -1,84 +0,0 @@ -# Copyright 2014 Mirantis, 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 sys - -import six -import yaml - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.objects.task import SnapshotTask - - -class SnapshotAction(Action): - """Generate and download snapshot. - """ - action_name = "snapshot" - - def __init__(self): - super(SnapshotAction, self).__init__() - self.args = ( - Args.get_boolean_arg("conf", - help_="Provide this flag to generate conf"), - ) - self.flag_func_map = ( - ('conf', self.get_snapshot_config), - (None, self.create_snapshot), - ) - - def create_snapshot(self, params): - """To create diagnostic snapshot: - fuel snapshot - - To specify config for snapshotting: - fuel snapshot < conf.yaml - - """ - if sys.stdin.isatty(): - conf = {} - else: - conf = yaml.load(sys.stdin.read()) - - snapshot_task = SnapshotTask.start_snapshot_task(conf) - self.serializer.print_to_output( - snapshot_task.data, - "Generating diagnostic snapshot..." - ) - snapshot_task.wait() - - if snapshot_task.status == 'ready': - self.serializer.print_to_output( - snapshot_task.data, - "...Completed...\n" - "Diagnostic snapshot can be downloaded from " + - snapshot_task.connection.root + - snapshot_task.data["message"] - ) - elif snapshot_task.status == 'error': - six.print_( - "Snapshot generating task ended with error. Task message: {0}" - .format(snapshot_task.data["message"]), - file=sys.stderr - ) - - def get_snapshot_config(self, params): - """Download default config for snapshot: - fuel snapshot --conf > dump_conf.yaml - - To use json formatter: - fuel snapshot --conf --json - """ - conf = SnapshotTask.get_default_config() - self.serializer.write_to_file(sys.stdout, conf) diff --git a/fuelclient/cli/actions/token.py b/fuelclient/cli/actions/token.py deleted file mode 100644 index 22b9e962..00000000 --- a/fuelclient/cli/actions/token.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2015 Mirantis, 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 sys - -from fuelclient.cli.actions.base import Action -from fuelclient.client import DefaultAPIClient - - -class TokenAction(Action): - """Return a valid keystone auth token - """ - action_name = "token" - - def __init__(self): - super(TokenAction, self).__init__() - - self.args = [] - self.flag_func_map = ( - (None, self.get_token), - ) - - def get_token(self, params): - """Print out a valid Keystone auth token - """ - sys.stdout.write(DefaultAPIClient.auth_token) diff --git a/fuelclient/cli/actions/user.py b/fuelclient/cli/actions/user.py deleted file mode 100644 index 79eae267..00000000 --- a/fuelclient/cli/actions/user.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from getpass import getpass - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli.error import ArgumentException -from fuelclient.client import DefaultAPIClient -from fuelclient import fuelclient_settings - - -class UserAction(Action): - """Change password for user - """ - action_name = "user" - - def __init__(self): - super(UserAction, self).__init__() - self.args = ( - Args.get_new_password_arg( - "WARNING: This method of changing the " - "password is dangerous - it may be saved in bash history."), - Args.get_change_password_arg( - "Change user password using interactive prompt") - ) - - self.flag_func_map = ( - ("change-password", self.change_password), - ) - - def _get_password_from_prompt(self): - password1 = getpass("Changing password for Fuel User.\nNew Password:") - password2 = getpass("Retype new Password:") - if password1 != password2: - raise ArgumentException("Passwords are not the same.") - return password1 - - def change_password(self, params): - """To change user password: - fuel user change-password - """ - if params.newpass: - password = params.newpass - else: - password = self._get_password_from_prompt() - - DefaultAPIClient.update_own_password(password) - settings = fuelclient_settings.get_settings() - self.serializer.print_to_output( - None, "\nPassword changed.\nPlease note that configuration " - "is not automatically updated.\nYou may want to update " - "{0}.".format( - settings.user_settings)) diff --git a/fuelclient/cli/actions/vip.py b/fuelclient/cli/actions/vip.py deleted file mode 100644 index bbd419a2..00000000 --- a/fuelclient/cli/actions/vip.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -from fuelclient.cli.actions.base import Action -import fuelclient.cli.arguments as Args -from fuelclient.cli import serializers -from fuelclient.objects.environment import Environment - - -class VIPAction(Action): - """Download or upload VIP settings of specific environments. - """ - action_name = "vip" - acceptable_keys = ("id", "upload", "download", "network", "network-role",) - - def __init__(self): - super(VIPAction, self).__init__() - # NOTE(aroma): 'serializer' attribute for action objects is - # overwritten while building parser object - # (fuelclient.cli.parser.Parser) - self.file_serializer = serializers.FileFormatBasedSerializer() - self.args = ( - Args.get_env_arg(required=True), - Args.get_create_arg("Create VIP"), - Args.get_upload_file_arg("Upload changed VIP configuration " - "from given file"), - Args.get_download_arg("Download VIP configuration"), - Args.get_file_arg("Target file with vip data."), - Args.get_ip_id_arg("IP address entity identifier"), - Args.get_ip_address_arg("IP address string"), - Args.get_network_id_arg("Network identifier"), - Args.get_network_role_arg("Network role string"), - Args.get_vip_name_arg("VIP name string"), - Args.get_vip_namespace_arg("VIP namespace string"), - ) - self.flag_func_map = ( - ("create", self.create), - ("upload", self.upload), - ("download", self.download) - ) - - def create(self, params): - """To create VIP for environment: - fuel --env 1 vip create --address 172.16.0.10 --network 1 \\ - --name public_vip --namespace haproxy - """ - env = Environment(params.env) - vip_kwargs = { - "ip_addr": getattr(params, 'ip-address'), - "network": getattr(params, 'network'), - "vip_name": getattr(params, 'vip-name'), - } - - vip_namespace = getattr(params, 'vip-namespace', None) - if vip_namespace is not None: - vip_kwargs['vip_namespace'] = vip_namespace - - env.create_vip(**vip_kwargs) - print("VIP has been created") - - def upload(self, params): - """To upload VIP configuration from some - file for some environment: - fuel --env 1 vip --upload vip.yaml - """ - env = Environment(params.env) - vips_data = env.read_vips_data_from_file( - file_path=params.upload, - serializer=self.file_serializer - ) - env.set_vips_data(vips_data) - print("VIP configuration uploaded.") - - def download(self, params): - """To download VIP configuration in this - file for some environment: - fuel --env 1 vip --download --file vip.yaml - where --file param is optional - """ - - env = Environment(params.env) - vips_data = env.get_vips_data( - ip_address_id=getattr(params, 'ip-address-id'), - network=getattr(params, 'network'), - network_role=getattr(params, 'network-role') - ) - vips_data_file_path = env.write_vips_data_to_file( - vips_data, - file_path=params.file, - serializer=self.serializer - ) - print( - "VIP configuration for environment with id={0}" - " downloaded to {1}".format(env.id, vips_data_file_path) - ) diff --git a/fuelclient/cli/arguments.py b/fuelclient/cli/arguments.py deleted file mode 100644 index e76e1097..00000000 --- a/fuelclient/cli/arguments.py +++ /dev/null @@ -1,787 +0,0 @@ -# Copyright 2014 Mirantis, 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 argparse -from itertools import chain -import os - -from fuelclient import __version__ -from fuelclient.cli.error import ArgumentException -from fuelclient.client import DefaultAPIClient - -substitutions = { - # replace from: to - "env": "environment", - "nodes": "node", - "statuses": "status", - "net": "network", - "rel": "release", - "list": "--list", - "set": "--set", - "delete": "--delete", - "download": "--download", - "upload": "--upload", - "default": "--default", - "create": "--create", - "remove": "--delete", - "config": "--config", - "--roles": "--role", - "help": "--help", - "change-password": "--change-password", - "hostname": "--hostname", -} - - -def group(*args, **kwargs): - required = kwargs.get("required", False) - return (required,) + args - - -class ArrayAction(argparse.Action): - """Custom argparse.Action subclass to store ids - - :returns: list of ids - """ - def __call__(self, parser, namespace, values, option_string=None): - list_ids = [int(value) for value in chain(*values)] - setattr(namespace, self.dest, list_ids) - - -class NodeAction(argparse.Action): - """Custom argparse.Action subclass to store node identity - - :returns: list of ids - """ - def __call__(self, parser, namespace, values, option_string=None): - if values: - node_identities = set(chain(*values)) - input_macs = set(n for n in node_identities if ":" in n) - only_ids = set() - for _id in (node_identities - input_macs): - try: - only_ids.add(int(_id)) - except ValueError: - raise ArgumentException( - "'{0}' is not valid node id.".format(_id)) - if input_macs: - nodes_mac_to_id_map = dict( - (n["mac"], n["id"]) - for n in DefaultAPIClient.get_request("nodes/") - ) - for short_mac in input_macs: - target_node = None - for mac in nodes_mac_to_id_map: - if mac.endswith(short_mac): - target_node = mac - break - if target_node: - only_ids.add(nodes_mac_to_id_map[target_node]) - else: - raise ArgumentException( - 'Node with mac endfix "{0}" was not found.' - .format(short_mac) - ) - node_ids = [int(node_id) for node_id in only_ids] - setattr(namespace, self.dest, node_ids) - - -class SetAction(argparse.Action): - """Custom argparse.Action subclass to store distinct values - - :returns: Set of arguments - """ - def __call__(self, _parser, namespace, values, option_string=None): - try: - getattr(namespace, self.dest).update(values) - except AttributeError: - setattr(namespace, self.dest, set(values)) - - -def get_debug_arg(): - return { - "args": ["--debug"], - "params": { - "dest": "debug", - "action": "store_true", - "help": "prints details of all HTTP request", - "default": False - } - } - - -def get_version_arg(): - return { - "args": ["-v", "--version"], - "params": { - "action": "version", - "version": __version__ - } - } - - -def get_arg(name, flags=None, aliases=None, help_=None, **kwargs): - name = name.replace("_", "-") - args = ["--" + name, ] - if flags is not None: - args.extend(flags) - if aliases is not None: - substitutions.update( - dict((alias, args[0]) for alias in aliases) - ) - all_args = { - "args": args, - "params": { - "dest": name, - "help": help_ or name - } - } - all_args["params"].update(kwargs) - return all_args - - -def get_boolean_arg(name, **kwargs): - kwargs.update({ - "action": "store_true", - "default": False - }) - return get_arg(name, **kwargs) - - -def get_env_arg(required=False): - return get_int_arg( - "env", - flags=("--env-id",), - help="environment id", - required=required - ) - - -def get_single_task_arg(required=False): - return get_int_arg( - "task", - flags=("--task-id", "--tid"), - help="task id", - required=required - ) - - -def get_new_password_arg(help_msg): - return get_str_arg( - "newpass", - flags=("--new-pass",), - help=help_msg, - required=False - ) - - -def get_str_arg(name, **kwargs): - default_kwargs = { - "action": "store", - "type": str, - "default": None - } - default_kwargs.update(kwargs) - return get_arg(name, **default_kwargs) - - -def get_int_arg(name, **kwargs): - default_kwargs = { - "action": "store", - "type": int, - "default": None - } - default_kwargs.update(kwargs) - return get_arg(name, **default_kwargs) - - -def get_array_arg(name, **kwargs): - default_kwargs = { - "action": ArrayAction, - "nargs": '+', - "type": lambda v: v.split(","), - "default": None - } - default_kwargs.update(kwargs) - return get_arg(name, **default_kwargs) - - -def get_set_type_arg(name, **kwargs): - default_kwargs = { - "type": lambda v: v.split(','), - "action": SetAction, - "default": None - } - default_kwargs.update(kwargs) - return get_arg(name, **default_kwargs) - - -def get_delete_from_db_arg(help_msg): - return get_boolean_arg("delete-from-db", help=help_msg) - - -def get_deployment_tasks_arg(help_msg): - return get_boolean_arg( - "deployment-tasks", help=help_msg) - - -def get_attributes_arg(help_msg): - return get_boolean_arg("attributes", help=help_msg) - - -def get_sync_deployment_tasks_arg(): - return get_boolean_arg( - "sync-deployment-tasks", - help="Update tasks for each release.") - - -def get_dry_run_deployment_arg(): - return get_boolean_arg( - "dry-run", - dest='dry_run', - help="Specifies to dry-run a deployment by configuring task executor" - "to dump the deployment graph to a dot file.") - - -def get_noop_run_deployment_arg(): - return get_boolean_arg( - "noop", - dest='noop_run', - help="Specifies noop-run deployment configuring tasks executor to run " - "puppet and shell tasks in noop mode and skip all other. " - "Stores noop-run result summary in nailgun database") - - -def get_file_pattern_arg(): - return get_str_arg( - "filepattern", - flags=("--fp", "--file-pattern"), - default="*tasks.yaml", - help="Provide unix file pattern to filter tasks with files.") - - -def get_node_name_arg(help_msg): - return get_str_arg("name", help=help_msg) - - -def get_hostname_arg(help_msg): - return get_str_arg("hostname", help=help_msg) - - -def get_network_arg(help_msg): - return get_boolean_arg("network", flags=("--net",), help=help_msg) - - -def get_force_arg(help_msg): - return get_boolean_arg("force", flags=("-f",), help=help_msg) - - -def get_disk_arg(help_msg): - return get_boolean_arg("disk", help=help_msg) - - -def get_deploy_arg(help_msg): - return get_boolean_arg("deploy", help=help_msg) - - -def get_provision_arg(help_msg): - return get_boolean_arg("provision", help=help_msg) - - -def get_role_arg(help_msg): - return get_set_type_arg("role", flags=("-r",), help=help_msg) - - -def get_single_role_arg(help_msg): - return get_str_arg("role", flags=('--role', ), help=help_msg) - - -def get_check_arg(help_msg): - return get_set_type_arg("check", help=help_msg) - - -def get_ostf_username_arg(): - return get_str_arg( - "ostf_username", - dest="ostf_username", - help="OSTF username", - required=False - ) - - -def get_ostf_password_arg(): - return get_str_arg( - "ostf_password", - dest="ostf_password", - help="OSTF password", - required=False - ) - - -def get_ostf_tenant_name_arg(): - return get_str_arg( - "ostf_tenant_name", - dest="ostf_tenant_name", - help="OSTF tenant name", - required=False - ) - - -def get_change_password_arg(help_msg): - return get_boolean_arg("change-password", help=help_msg) - - -def get_name_arg(help_msg): - return get_str_arg("name", flags=("--env-name",), help=help_msg) - - -def get_graph_endpoint(): - return get_arg( - 'end', - action="store", - default=None, - help="Specify endpoint for the graph traversal.", - metavar='TASK', - ) - - -def get_graph_startpoint(): - return get_arg( - 'start', - action="store", - default=None, - help="Specify start point for the graph traversal.", - metavar='TASK', - ) - - -def get_skip_tasks(): - return get_arg( - 'skip', - nargs='+', - default=[], - help="Get list of tasks to be skipped.", - metavar='TASK', - ) - - -def get_tasks(): - return get_arg( - 'tasks', - nargs='+', - default=[], - help="Get list of tasks to be executed.", - metavar='TASK', - ) - - -def get_parents_arg(): - return get_arg( - 'parents-for', - help="Get parent for given task", - metavar='TASK', - ) - - -def get_remove_type_arg(types): - return get_arg( - 'remove', - nargs='+', - default=[], - choices=types, - help="Select task types to remove from graph.", - ) - - -def get_nst_arg(help_msg): - return get_arg("nst", - flags=("--net-segment-type",), - action="store", - choices=("gre", "vlan", "tun"), - help_=help_msg, - default="vlan") - - -def get_all_arg(help_msg): - return get_boolean_arg("all", help=help_msg) - - -def get_create_arg(help_msg): - return get_boolean_arg( - "create", - flags=("-c", "--env-create"), - help=help_msg) - - -def get_download_arg(help_msg): - return get_boolean_arg("download", flags=("-d",), help=help_msg) - - -def get_list_arg(help_msg): - return get_boolean_arg("list", flags=("-l",), help=help_msg) - - -def get_dir_arg(help_msg): - return get_str_arg("dir", default=os.curdir, help=help_msg) - - -def get_file_arg(help_msg): - return get_str_arg("file", help=help_msg) - - -def get_verify_arg(help_msg): - return get_boolean_arg("verify", flags=("-v",), help=help_msg) - - -def get_upload_arg(help_msg): - return get_boolean_arg("upload", flags=("-u",), help=help_msg) - - -def get_default_arg(help_msg): - return get_boolean_arg("default", help=help_msg) - - -def get_set_arg(help_msg): - return get_boolean_arg("set", flags=("-s",), help=help_msg) - - -def get_delete_arg(help_msg): - return get_boolean_arg("delete", help=help_msg) - - -def get_execute_arg(help_msg): - return get_boolean_arg("execute", help=help_msg) - - -def get_assign_arg(help_msg): - return get_boolean_arg("assign", help=help_msg) - - -def get_group_arg(help_msg): - return get_set_type_arg("group", help=help_msg) - - -def get_node_group_arg(help_msg): - return get_set_type_arg("nodegroup", flags=("--node-group",), - help=help_msg) - - -def get_vlan_arg(help_msg): - return get_int_arg("vlan", help=help_msg) - - -def get_cidr_arg(help_msg): - return get_str_arg("cidr", help=help_msg) - - -def get_gateway_arg(help_msg): - return get_str_arg("gateway", help=help_msg) - - -def get_meta_arg(help_msg): - return get_str_arg("meta", help=help_msg) - - -def get_create_network_arg(help_msg): - return get_boolean_arg( - "create", - flags=("-c", "--create"), - help=help_msg) - - -def get_network_group_arg(help_msg): - return get_set_type_arg("network", help=help_msg) - - -def get_release_arg(help_msg, required=False): - return get_int_arg( - "release", - flags=("--rel",), - required=required, - help=help_msg) - - -def get_render_arg(help_msg): - return get_str_arg( - "render", - metavar='INPUT', - help=help_msg) - - -def get_tred_arg(help_msg): - return get_boolean_arg("tred", help=help_msg) - - -def get_node_arg(help_msg): - default_kwargs = { - "action": NodeAction, - "flags": ("--node-id",), - "nargs": '+', - "type": lambda v: v.split(","), - "default": None, - "help": help_msg - } - return get_arg("node", **default_kwargs) - - -def get_single_node_arg(help_msg): - return get_int_arg('node', flags=('--node-id',), help=help_msg) - - -def get_task_arg(help_msg): - return get_array_arg( - 'task', - flags=("--task-id", "--tid"), - help=help_msg - ) - - -def get_config_id_arg(help_msg): - return get_int_arg( - 'config-id', - help=help_msg) - - -def get_deleted_arg(help_msg): - return get_boolean_arg( - 'deleted', help=help_msg) - - -def get_plugin_install_arg(help_msg): - return get_str_arg( - "install", - metavar='PLUGIN_FILE', - help=help_msg - ) - - -def get_plugin_remove_arg(help_msg): - return get_str_arg( - "remove", - metavar='PLUGIN_NAME==VERSION', - help=help_msg - ) - - -def get_plugin_register_arg(help_msg): - return get_str_arg( - "register", - metavar='PLUGIN_NAME==VERSION', - help=help_msg - ) - - -def get_plugin_unregister_arg(help_msg): - return get_str_arg( - "unregister", - metavar='PLUGIN_NAME==VERSION', - help=help_msg - ) - - -def get_plugin_update_arg(help_msg): - return get_str_arg( - "update", - metavar='PLUGIN_FILE', - help=help_msg - ) - - -def get_plugin_downgrade_arg(help_msg): - return get_str_arg( - "downgrade", - metavar='PLUGIN_FILE', - help=help_msg - ) - - -def get_plugin_sync_arg(help_msg): - return get_boolean_arg( - "sync", - help=help_msg - ) - - -def get_plugin_arg(help_msg): - return get_array_arg( - 'plugin', - flags=('--plugin-id',), - help=help_msg - ) - - -def get_notify_all_messages_arg(help_msg): - return get_boolean_arg( - 'all', - flags=('-a',), - help=help_msg - ) - - -def get_notify_mark_as_read_arg(help_msg): - return get_str_arg( - "mark-as-read", - flags=('-r',), - nargs='+', - help=help_msg, - ) - - -def get_notify_message_arg(help_msg): - return get_str_arg( - "send", - nargs='+', - flags=('-m',), - help=help_msg, - ) - - -def get_notify_send_arg(help_msg): - return get_str_arg( - "send", - flags=("--send",), - help=help_msg - ) - - -def get_notify_topic_arg(help_msg): - return get_str_arg( - "topic", - flags=("--topic",), - choices=( - 'discover', - 'done', - 'error', - 'warning', - 'release' - ), - help=help_msg - ) - - -def get_vip_arg(help_msg): - return get_boolean_arg( - "vip", - flags=("--vip",), - help=help_msg - ) - - -def get_vip_name_arg(help_msg): - return get_str_arg( - "vip-name", - flags=("--name",), - help=help_msg - ) - - -def get_vip_namespace_arg(help_msg, required=False): - return get_str_arg( - "vip-namespace", - flags=("--namespace",), - required=required, - help=help_msg - ) - - -def get_ip_address_arg(help_msg): - return get_str_arg( - "ip-address", - flags=("--address", "--ip-addr"), - help=help_msg - ) - - -def get_ip_id_arg(help_msg): - return get_int_arg( - "ip-address-id", - flags=("--ip-address-id",), - help=help_msg - ) - - -def get_network_id_arg(help_msg): - return get_int_arg( - "network", - flags=("--network",), - help=help_msg - ) - - -def get_network_role_arg(help_msg): - return get_str_arg( - "network-role", - flags=("--network-role",), - help=help_msg - ) - - -def get_upload_file_arg(help_msg): - return get_str_arg( - "upload", - flags=("-u", "--upload",), - help=help_msg - ) - - -def get_status_arg(help_msg): - default_kwargs = { - "flags": ("--status",), - "default": None, - "help": help_msg - } - return get_arg("status", **default_kwargs) - - -def get_deployment_node_arg(help_msg): - default_kwargs = { - "flags": ("--node-id",), - "default": None, - "help": help_msg - } - return get_arg("node", **default_kwargs) - - -def get_tasks_names_arg(help_msg): - default_kwargs = { - "flags": ("-d", "--task-name",), - "default": None, - "help": help_msg - } - return get_arg("task-name", **default_kwargs) - - -def get_show_parameters_arg(help_msg): - default_kwargs = { - "flags": ("-p", "--show-parameters",), - "help": help_msg - } - return get_boolean_arg("show-parameters", **default_kwargs) - - -def get_include_summary_arg(help_msg): - default_kwargs = { - "flags": ("--include-summary",), - "help": help_msg - } - return get_boolean_arg("include-summary", **default_kwargs) - - -def get_not_split_facts_args(): - kwargs = { - "action": "store_false", - "default": True, - "dest": "split", - "help": "Do not split deployment info for node and cluster parts." - } - return get_arg('no-split', **kwargs) diff --git a/fuelclient/cli/error.py b/fuelclient/cli/error.py deleted file mode 100644 index f069b845..00000000 --- a/fuelclient/cli/error.py +++ /dev/null @@ -1,155 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from functools import wraps -import json -import os -import sys - -from keystoneclient.exceptions import Unauthorized -import requests -import textwrap - - -def exit_with_error(message): - """exit_with_error - writes message to stderr and exits with exit code 1. - """ - sys.stderr.write("{}{}".format(message, os.linesep)) - exit(1) - - -class FuelClientException(Exception): - """Base Exception for Fuel-Client - - All child classes must be instantiated before raising. - """ - def __init__(self, *args, **kwargs): - super(FuelClientException, self).__init__(*args, **kwargs) - self.message = args[0] - - -class BadDataException(FuelClientException): - """Should be raised when user provides corrupted data.""" - - -class WrongEnvironmentError(FuelClientException): - """Raised when particular action is not supported on environment.""" - - -class ServerDataException(FuelClientException): - """ServerDataException - must be raised when - data returned from server cannot be processed by Fuel-Client methods. - """ - - -class DeployProgressError(FuelClientException): - """DeployProgressError - must be raised when - deployment process interrupted on server. - """ - - -class ArgumentException(FuelClientException): - """ArgumentException - must be raised when - incorrect arguments inputted through argparse or some function. - """ - - -class ActionException(FuelClientException): - """ActionException - must be raised when - though arguments inputted to action are correct but they contradict - to logic in action. - """ - - -class ParserException(FuelClientException): - """ParserException - must be raised when - some problem occurred in process of argument parsing, - in argparse extension or in Fuel-Client Parser submodule. - """ - - -class ProfilingError(FuelClientException): - """Indicates errors and other issues related to performance profiling.""" - - -class SettingsException(FuelClientException): - """Indicates errors or unexpected behaviour in processing settings.""" - - -class ExecutedErrorNonZeroExitCode(FuelClientException): - """Subshell command returned non-zero exit code.""" - - -class LabelEmptyKeyError(BadDataException): - """Should be raised when user provides labels with empty key.""" - - -class InvalidDirectoryException(FuelClientException): - pass - - -class InvalidFileException(FuelClientException): - pass - - -class HTTPError(FuelClientException): - pass - - -class EnvironmentException(Exception): - pass - - -def exceptions_decorator(func): - """Handles HTTP errors and expected exceptions that may occur - in methods of DefaultAPIClient class - """ - @wraps(func) - def wrapper(*args, **kwargs): - try: - return func(*args, **kwargs) - - # when server returns to us bad request check that - # and print meaningful reason - except HTTPError as exc: - exit_with_error(exc) - except requests.ConnectionError: - message = """ - Can't connect to Nailgun server! - Please check connection settings in your configuration file.""" - exit_with_error(textwrap.dedent(message).strip()) - except Unauthorized: - message = """ - Unauthorized: need authentication! - Please provide user and password via client - fuel --os-username=user --os-password=pass [action] - or modify your credentials in your configuration file.""" - exit_with_error(textwrap.dedent(message).strip()) - except FuelClientException as exc: - exit_with_error(exc.message) - - return wrapper - - -def get_error_body(error): - try: - error_body = json.loads(error.response.text)['message'] - except (ValueError, TypeError, KeyError): - error_body = error.response.text - - return error_body - - -def get_full_error_message(error): - return "{} ({})".format(error, get_error_body(error)) diff --git a/fuelclient/cli/formatting.py b/fuelclient/cli/formatting.py deleted file mode 100644 index 7788b97a..00000000 --- a/fuelclient/cli/formatting.py +++ /dev/null @@ -1,161 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from itertools import chain -from operator import itemgetter -from time import sleep - -import six - - -def format_table(data, acceptable_keys=None, column_to_join=None): - """Format list of dicts to table in a string form - - :acceptable_keys list(str): list of keys for which to create table - also specifies their order - """ - - # prepare columns - if column_to_join is not None: - for data_dict in data: - for column_name in column_to_join: - data_dict[column_name] = u", ".join( - sorted(data_dict[column_name]) - ) - if acceptable_keys is not None: - rows = [tuple(value.get(key, "") for key in acceptable_keys) - for value in data] - header = tuple(acceptable_keys) - else: - rows = [tuple(x.values()) for x in data] - header = tuple(data[0].keys()) - number_of_columns = len(header) - - # split multi-lines cells if there is no automatic columns merge - if column_to_join: - def format_cell(cell): - return [cell or ""] - else: - def format_cell(cell): - return six.text_type(cell).split('\n') - rows = [ - [format_cell(cell) if cell is not None else [''] for cell in row] - for row in rows - ] - - # calculate columns widths - column_widths = dict( - zip( - range(number_of_columns), - (len(str(x)) for x in header) - ) - ) - for row in rows: - column_widths.update( - ( - index, - max( - column_widths[index], - max(len(six.text_type(line)) for line in cell) - ) - ) - for index, cell in enumerate(row) - ) - - # make output - hor_delimeter = u'-+-'.join(column_widths[column_index] * u'-' - for column_index in range(number_of_columns)) - - row_template = u' | '.join( - u"{{{0}:{1}}}".format(idx, width) - for idx, width in column_widths.items() - ) - - output_lines = [ - row_template.format(*header), - hor_delimeter - ] - - for row in rows: - max_cell_lines = max(len(cell) for cell in row) - for cell_line_no in range(max_cell_lines): - output_lines.append( - row_template.format( - *( - cell[cell_line_no] if len(cell) > cell_line_no else u"" - for cell in row - ) - ) - ) - return u'\n'.join(output_lines) - - -def quote_and_join(words): - """quote_and_join - performs listing of objects and returns string. - """ - words = list(words) - if len(words) > 1: - return '{0} and "{1}"'.format( - ", ".join( - ['"{0}"'.format(x) for x in words][:-1] - ), - words[-1] - ) - else: - return '"{0}"'.format(words[0]) - - -# TODO(vkulanov): remove when deprecate old cli -def print_health_check(env): - tests_states = [{"status": "not finished"}] - finished_tests = set() - test_counter, total_tests_count = 1, None - while not all(map( - lambda t: t["status"] == "finished", - tests_states - )): - tests_states = env.get_state_of_tests() - all_tests = list(chain(*map( - itemgetter("tests"), - filter( - env.is_in_running_test_sets, - tests_states - )))) - if total_tests_count is None: - total_tests_count = len(all_tests) - all_finished_tests = filter( - lambda t: "running" not in t["status"], - all_tests - ) - new_finished_tests = filter( - lambda t: t["name"] not in finished_tests, - all_finished_tests - ) - finished_tests.update( - map( - itemgetter("name"), - new_finished_tests - ) - ) - for test in new_finished_tests: - print( - u"[{0:2} of {1}] [{status}] '{name}' " - u"({taken:.4} s) {message}".format( - test_counter, - total_tests_count, - **test - ) - ) - test_counter += 1 - sleep(1) diff --git a/fuelclient/cli/parser.py b/fuelclient/cli/parser.py deleted file mode 100644 index 2e9cf795..00000000 --- a/fuelclient/cli/parser.py +++ /dev/null @@ -1,246 +0,0 @@ -# Copyright 2014 Mirantis, 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 argparse -import sys - -from fuelclient.cli.actions import actions -from fuelclient.cli.arguments import get_version_arg -from fuelclient.cli.arguments import substitutions -from fuelclient.cli.error import exceptions_decorator -from fuelclient.cli.error import ParserException -from fuelclient.cli.serializers import Serializer -from fuelclient import consts -from fuelclient import fuelclient_settings -from fuelclient import profiler -from fuelclient import utils - - -class Parser(object): - """Parser class - encapsulates argparse's ArgumentParser - and based on available actions, serializers and additional flags - populates it. - """ - def __init__(self, argv): - self.args = argv - self.parser = argparse.ArgumentParser( - usage=""" - fuel [optional args] [action] [flags] - - DEPRECATION WARNING: - - In an upcoming release of Fuel Client, the syntax will - be changed to the following: - - fuel [general flags] [action flags] - - where both [general flags] and [action flags] are derivatives - from [optional args] and [flags]; is a derivative from - . Keep in mind that specifying will be - mandatory. - - Some of the [optional args] are going to specific to a - particular and context in the upcoming - release of Fuel Client, so specifying them - before either or will not be possible. - - Example: - Correct: fuel node list --env 1 - Wrong: fuel --env 1 node list - - The table below describes the upcoming changes to commands - which will be removed or changed significantly. - - +--------------------------------------------------------+ - | Old command | New command | - +------------------------+-------------------------------+ - | fuel deploy-changes | fuel env deploy | - +------------------------+-------------------------------+ - | fuel node --set --env | fuel env add nodes | - +------------------------+-------------------------------+ - | fuel network <> --env | fuel env network <> | - +------------------------+-------------------------------+ - | fuel settings <> --env | fuel env settings <> | - +------------------------+-------------------------------+ - | fuel stop | fuel env stop-deploy | - +------------------------+-------------------------------+ - - Further information will be located in Fuel Documentation and - on our Wiki page: https://wiki.openstack.org/wiki/Fuel_CLI - - You can check out an experimental version of the new - Fuel Client by using the following command: - - fuel2 --help - - """ - ) - self.universal_flags = [] - self.credential_flags = [] - self.subparsers = self.parser.add_subparsers( - title="Namespaces", - metavar="", - dest="action", - help='actions' - ) - self.generate_actions() - self.add_version_args() - self.add_debug_arg() - self.add_serializers_args() - utils.add_os_cli_parameters(self.parser) - - def generate_actions(self): - for action, action_object in actions.items(): - action_parser = self.subparsers.add_parser( - action, - prog="fuel {0}".format(action), - help=action_object.__doc__, - formatter_class=argparse.RawTextHelpFormatter, - epilog=action_object.examples - ) - for argument in action_object.args: - if isinstance(argument, dict): - action_parser.add_argument( - *argument["args"], - **argument["params"] - ) - elif isinstance(argument, tuple): - required = argument[0] - group = action_parser.add_mutually_exclusive_group( - required=required) - for argument_in_group in argument[1:]: - group.add_argument( - *argument_in_group["args"], - **argument_in_group["params"] - ) - - def parse(self): - self.prepare_args() - if len(self.args) < 2: - self.parser.print_help() - sys.exit(0) - - parsed_params = self.parser.parse_args(self.args[1:]) - - settings = fuelclient_settings.get_settings() - settings.update_from_command_line_options(parsed_params) - - if parsed_params.action not in actions: - self.parser.print_help() - sys.exit(0) - - if profiler.profiling_enabled(): - handler_name = parsed_params.action - method_name = ''.join([method for method in parsed_params.__dict__ - if getattr(parsed_params, method) is True]) - prof = profiler.Profiler(method_name, handler_name) - - actions[parsed_params.action].action_func(parsed_params) - - if profiler.profiling_enabled(): - prof.save_data() - - def add_serializers_args(self): - serializers = self.parser.add_mutually_exclusive_group() - for format_name in Serializer.serializers.keys(): - serialization_flag = "--{0}".format(format_name) - self.universal_flags.append(serialization_flag) - serializers.add_argument( - serialization_flag, - dest=consts.SERIALIZATION_FORMAT_FLAG, - action="store_const", - const=format_name, - help="prints only {0} to stdout".format(format_name), - default=False - ) - - def add_debug_arg(self): - self.universal_flags.append("--debug") - self.parser.add_argument( - "--debug", - dest="debug", - action="store_true", - help="prints details of all HTTP request", - default=False - ) - - def add_version_args(self): - arg = get_version_arg() - self.parser.add_argument(*arg["args"], **arg["params"]) - - def prepare_args(self): - # replace some args from dict substitutions - self.args = [substitutions.get(arg, arg) for arg in self.args] - - # move general used flags before actions, otherwise they will be used - # as a part of action by action_generator - for flag in self.credential_flags: - self.move_argument_before_action(flag) - - for flag in self.universal_flags: - self.move_argument_before_action(flag, has_value=False) - - self.move_argument_after_action("--env",) - - def move_argument_before_action(self, flag, has_value=True): - """We need to move general argument before action, we use them - not directly in action but in DefaultAPIClient. - """ - for arg in self.args: - if flag in arg: - if "=" in arg or not has_value: - index_of_flag = self.args.index(arg) - flag = self.args.pop(index_of_flag) - self.args.insert(1, flag) - else: - try: - index_of_flag = self.args.index(arg) - flag = self.args.pop(index_of_flag) - value = self.args.pop(index_of_flag) - self.args.insert(1, value) - self.args.insert(1, flag) - except IndexError: - raise ParserException( - 'Corresponding value must follow "{0}" flag' - .format(arg) - ) - break - - def move_argument_after_action(self, flag): - for arg in self.args: - if flag in arg: - # if declaration with '=' sign (e.g. --env-id=1) - if "=" in arg: - index_of_flag = self.args.index(arg) - flag = self.args.pop(index_of_flag) - self.args.append(flag) - else: - try: - index_of_flag = self.args.index(arg) - self.args.pop(index_of_flag) - flag = self.args.pop(index_of_flag) - self.args.append(arg) - self.args.append(flag) - except IndexError: - raise ParserException( - 'Corresponding value must follow "{0}" flag' - .format(arg) - ) - break - - -@exceptions_decorator -def main(args=sys.argv): - parser = Parser(args) - parser.parse() diff --git a/fuelclient/cli/serializers.py b/fuelclient/cli/serializers.py deleted file mode 100644 index 9678b400..00000000 --- a/fuelclient/cli/serializers.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright 2014 Mirantis, 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. -from __future__ import print_function - -import json -import os - -import six -import yaml - -from fuelclient.cli import error -from fuelclient import consts -from fuelclient import utils - - -class Serializer(object): - """Serializer class - contains all logic responsible for - printing to stdout, reading and writing files to file system. - """ - serializers = { - "json": { - "w": lambda d: json.dumps(d, indent=4), - "r": utils.safe_deserialize(json.loads) - }, - "yaml": { - "w": lambda d: yaml.safe_dump(d, default_flow_style=False), - "r": utils.safe_deserialize(yaml.load) - } - } - - format_flags = False - default_format = "yaml" - format = default_format - - def __init__(self, format=None): - if format and format in self.serializers: - self.format = format - self.format_flags = True - - @property - def serializer(self): - """Returns dicts with methods for loadin/dumping current fromat. - - Returned dict's keys: - * 'w' - from 'writing', method for serializing/dumping data - * 'r' - from 'reading', method for deserializing/loading data - """ - return self.serializers[self.format] - - def serialize(self, data): - """Shortcut for serializing data with current format.""" - return self.serializer['w'](data) - - def deserialize(self, data): - """Shortcut for deserializing data with current format.""" - return self.serializer['r'](data) - - @classmethod - def from_params(cls, params): - return cls(format=getattr(params, - consts.SERIALIZATION_FORMAT_FLAG, None)) - - def print_formatted(self, data): - print(self.serializer["w"](data)) - - def print_to_output(self, formatted_data, arg, print_method=print): - if self.format_flags: - self.print_formatted(formatted_data) - else: - if six.PY2 and isinstance(arg, six.text_type): - arg = arg.encode('utf-8') - print_method(arg) - - def prepare_path(self, path): - return "{0}.{1}".format( - path, self.format - ) - - def write_to_path(self, path, data): - full_path = self.prepare_path(path) - return self.write_to_full_path(full_path, data) - - def write_to_full_path(self, path, data): - try: - with open(path, "w") as file_to_write: - self.write_to_file(file_to_write, data) - except IOError as e: - raise error.InvalidFileException( - "Can't write to file '{0}': {1}.".format( - path, e.strerror)) - return path - - def read_from_file(self, path): - return self.read_from_full_path(self.prepare_path(path)) - - def read_from_full_path(self, full_path): - try: - with open(full_path, "r") as file_to_read: - return self.serializer["r"](file_to_read.read()) - except IOError as e: - raise error.InvalidFileException( - "Can't open file '{0}': {1}.".format(full_path, e.strerror)) - - def write_to_file(self, file_obj, data): - """Writes to opened file or file like object - :param file_obj: opened file - :param data: any serializable object - """ - serialized = self.serializer["w"](data) - file_obj.write(serialized) - - -class FileFormatBasedSerializer(Serializer): - - def get_serializer(self, path): - extension = os.path.splitext(path)[1][1:] - if extension not in self.serializers: - raise error.BadDataException( - 'No serializer for provided file {0}'.format(path)) - return self.serializers[extension] - - def write_to_file(self, full_path, data): - serializer = self.get_serializer(full_path) - with open(full_path, "w+") as f: - f.write(serializer["w"](data)) - return full_path - - def read_from_file(self, full_path): - serializer = self.get_serializer(full_path) - with open(full_path, "r") as f: - return serializer["r"](f.read()) - - -def listdir_without_extensions(dir_path): - return six.moves.filter( - lambda f: f != "", - six.moves.map( - lambda f: f.split(".")[0], - os.listdir(dir_path) - ) - ) diff --git a/fuelclient/client.py b/fuelclient/client.py deleted file mode 100644 index 36a77720..00000000 --- a/fuelclient/client.py +++ /dev/null @@ -1,248 +0,0 @@ -# Copyright 2014 Mirantis, 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 json -import requests - -from keystoneclient.v2_0 import client as auth_client -from six.moves.urllib import parse as urlparse - -from fuelclient.cli import error -from fuelclient import fuelclient_settings - - -class APIClient(object): - """This class handles API requests - """ - - def __init__(self, host, port, http_proxy=None, http_timeout=None, - os_username=None, os_password=None, - os_tenant_name=None, debug=False): - self.debug = debug - - self._http_proxy = http_proxy - self._http_timeout = http_timeout - self._os_username = os_username - self._os_password = os_password - self._os_tenant_name = os_tenant_name - - self.root = "http://{host}:{port}".format(host=host, port=port) - - self.keystone_base = urlparse.urljoin(self.root, "/keystone/v2.0") - self.api_root = urlparse.urljoin(self.root, "/api/v1/") - self.ostf_root = urlparse.urljoin(self.root, "/ostf/") - - self._keystone_client = None - self._auth_required = None - self._session = None - - @classmethod - def default_client(cls): - conf = fuelclient_settings.get_settings() - return cls( - host=conf.SERVER_ADDRESS, - port=conf.SERVER_PORT, - http_proxy=conf.HTTP_PROXY, - http_timeout=conf.HTTP_TIMEOUT, - os_username=conf.OS_USERNAME, - os_password=conf.OS_PASSWORD, - os_tenant_name=conf.OS_TENANT_NAME - ) - - def _make_common_headers(self): - """Returns a dict of HTTP headers common for all requests.""" - - return {'Content-Type': 'application/json', - 'Accept': 'application/json', - 'X-Auth-Token': self.auth_token} - - def _make_proxies(self): - """Provides HTTP proxy configuration for requests module.""" - if self._http_proxy is None: - return None - - return {'http': self._http_proxy, - 'https': self._http_proxy} - - def _make_session(self): - """Initializes a HTTP session.""" - session = requests.Session() - session.headers.update(self._make_common_headers()) - session.timeout = self._http_timeout - session.proxies = self._make_proxies() - - return session - - @property - def session(self): - """Lazy initialization of a session - - Since HTTP client is a singleton test runners cannot - collect tests due to keystone authentication issues. - - TODO(romcheg): remove lazy initialization for session - when HTTP client is not a singleton. - - """ - if self._session is None: - self._session = self._make_session() - - return self._session - - @property - def auth_token(self): - if self.auth_required: - if not self.keystone_client.auth_token: - self.keystone_client.authenticate() - return self.keystone_client.auth_token - return '' - - @property - def auth_required(self): - if self._auth_required is None: - url = self.api_root + 'version' - resp = requests.get(url) - if resp.status_code == 401: - self._auth_required = True - else: - self._raise_for_status_with_info(resp) - self._auth_required = resp.json().get('auth_required', False) - - return self._auth_required - - @property - def keystone_client(self): - if not self._keystone_client: - self.initialize_keystone_client() - return self._keystone_client - - def update_own_password(self, new_pass): - if self.auth_token: - self.keystone_client.users.update_own_password( - self._os_password, new_pass) - - def initialize_keystone_client(self): - if self.auth_required: - self._keystone_client = auth_client.Client( - auth_url=self.keystone_base, - username=self._os_username, - password=self._os_password, - tenant_name=self._os_tenant_name) - - self._keystone_client.session.auth = self._keystone_client - self._keystone_client.authenticate() - - def debug_mode(self, debug=False): - self.debug = debug - return self - - def print_debug(self, message): - if self.debug: - print(message) - - def delete_request(self, api): - """Make DELETE request to specific API with some data.""" - - url = self.api_root + api - self.print_debug('DELETE {0}'.format(url)) - - resp = self.session.delete(url) - self._raise_for_status_with_info(resp) - - return self._decode_content(resp) - - def put_request(self, api, data, ostf=False, **params): - """Make PUT request to specific API with some data. - - :param api: API endpoint (path) - :param data: Data send in request, will be serialized to JSON - :param ostf: is this a call to OSTF API - :param params: Params of query string - """ - url = (self.ostf_root if ostf else self.api_root) + api - data_json = json.dumps(data) - resp = self.session.put(url, data=data_json, params=params) - - self.print_debug('PUT {0} data={1}'.format(resp.url, data_json)) - self._raise_for_status_with_info(resp) - return self._decode_content(resp) - - def get_request_raw(self, api, ostf=False, params=None): - """Make a GET request to specific API and return raw response - - :param api: API endpoint (path) - :param ostf: is this a call to OSTF API - :param params: params passed to GET request - - """ - url = (self.ostf_root if ostf else self.api_root) + api - self.print_debug('GET {0}'.format(url)) - - return self.session.get(url, params=params) - - def get_request(self, api, ostf=False, params=None): - """Make GET request to specific API.""" - - params = params or {} - - resp = self.get_request_raw(api, ostf, params) - self._raise_for_status_with_info(resp) - - return resp.json() - - def post_request_raw(self, api, data=None, ostf=False): - """Make a POST request to specific API and return raw response. - - :param api: API endpoint (path) - :param data: data send in request, will be serialzied to JSON - :param ostf: is this a call to OSTF API - - """ - url = (self.ostf_root if ostf else self.api_root) + api - data_json = None if data is None else json.dumps(data) - - self.print_debug('POST {0} data={1}'.format(url, data_json)) - - return self.session.post(url, data=data_json) - - def post_request(self, api, data=None, ostf=False): - """Make POST request to specific API with some data - """ - resp = self.post_request_raw(api, data, ostf=ostf) - self._raise_for_status_with_info(resp) - return self._decode_content(resp) - - def get_fuel_version(self): - return self.get_request("version") - - def _raise_for_status_with_info(self, response): - try: - response.raise_for_status() - except requests.exceptions.HTTPError as e: - raise error.HTTPError(error.get_full_error_message(e)) - - def _decode_content(self, response): - if response.status_code == 204: - return {} - - self.print_debug(response.text) - return response.json() - - -# This line is single point of instantiation for 'APIClient' class, -# which intended to implement Singleton design pattern. -DefaultAPIClient = APIClient.default_client() -""" -.. deprecated:: Use fuelclient.client.APIClient instead -""" diff --git a/fuelclient/commands/__init__.py b/fuelclient/commands/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/commands/base.py b/fuelclient/commands/base.py deleted file mode 100644 index 234f08c4..00000000 --- a/fuelclient/commands/base.py +++ /dev/null @@ -1,253 +0,0 @@ -# Copyright 2015 Mirantis, 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 abc -import os - -from cliff import command -from cliff import lister -from cliff import show -import six - -import fuelclient -from fuelclient.cli.serializers import Serializer -from fuelclient.common import data_utils - -VERSION = 'v1' - - -@six.add_metaclass(abc.ABCMeta) -class BaseCommand(command.Command): - """Base Fuel Client command.""" - - def get_attributes_path(self, attr_type, file_format, ent_id, directory): - """Returnes a path for attributes of an entity - - :param attr_type: Type of the attribute, e. g., disks, networks. - :param file_format: The format of the file that contains or will - contain the attributes, e. g., json or yaml. - :param ent_id: Id of an entity - :param directory: Directory that is used to store attributes. - - """ - if attr_type not in self.allowed_attr_types: - raise ValueError('attr_type must be ' - 'one of {}'.format(self.allowed_attr_types)) - - if file_format not in self.supported_file_formats: - raise ValueError('file_format must be ' - 'one of {}'.format(self.supported_file_formats)) - - return os.path.join(os.path.abspath(directory), - '{ent}_{id}'.format(ent=self.entity_name, - id=ent_id), - '{}.{}'.format(attr_type, file_format)) - - def __init__(self, *args, **kwargs): - super(BaseCommand, self).__init__(*args, **kwargs) - self.client = fuelclient.get_client(self.entity_name, VERSION) - - @abc.abstractproperty - def entity_name(self): - """Name of the Fuel entity.""" - pass - - @property - def supported_file_formats(self): - raise NotImplementedError() - - @property - def allowed_attr_types(self): - raise NotImplementedError() - - -@six.add_metaclass(abc.ABCMeta) -class BaseListCommand(lister.Lister, BaseCommand): - """Lists all entities showing some information.""" - - filters = {} - - @property - def default_sorting_by(self): - return ['id'] - - @abc.abstractproperty - def columns(self): - """Names of columns in the resulting table.""" - pass - - def get_parser(self, prog_name): - parser = super(BaseListCommand, self).get_parser(prog_name) - - # Add sorting key argument to the output formatters group - # if it exists. If not -- add is to the general group. - matching_groups = (gr - for gr in parser._action_groups - if gr.title == 'output formatters') - - group = next(matching_groups, None) or parser - - group.add_argument('-s', - '--sort-columns', - type=str, - nargs='+', - choices=self.columns, - metavar='SORT_COLUMN', - default=self.default_sorting_by, - help='Space separated list of keys for sorting ' - 'the data. Defaults to {}. Wrong values ' - 'are ignored.'.format( - ', '.join(self.default_sorting_by))) - - return parser - - def _sort_data(self, parsed_args, data): - scolumn_ids = [self.columns.index(col) - for col in parsed_args.sort_columns] - data.sort(key=lambda x: [x[scolumn_id] for scolumn_id in scolumn_ids]) - return data - - def take_action(self, parsed_args): - filters = {} - for name, prop in self.filters.items(): - value = getattr(parsed_args, prop, None) - if value is not None: - filters[name] = value - - data = self.client.get_all(**filters) - data = data_utils.get_display_data_multi(self.columns, data) - data = self._sort_data(parsed_args, data) - - return self.columns, data - - -@six.add_metaclass(abc.ABCMeta) -class BaseShowCommand(show.ShowOne, BaseCommand): - """Shows detailed information about the entity.""" - - @abc.abstractproperty - def columns(self): - """Names of columns in the resulting table.""" - pass - - def get_parser(self, prog_name): - parser = super(BaseShowCommand, self).get_parser(prog_name) - - parser.add_argument('id', type=int, - help='Id of the {0}.'.format(self.entity_name)) - - return parser - - def take_action(self, parsed_args): - data = self.client.get_by_id(parsed_args.id) - data = data_utils.get_display_data_single(self.columns, data) - - return (self.columns, data) - - -@six.add_metaclass(abc.ABCMeta) -class BaseDeleteCommand(BaseCommand): - """Deletes entity with the specified id.""" - - def get_parser(self, prog_name): - parser = super(BaseDeleteCommand, self).get_parser(prog_name) - - parser.add_argument( - 'id', - type=int, - help='Id of the {0} to delete.'.format(self.entity_name)) - - return parser - - def take_action(self, parsed_args): - self.client.delete_by_id(parsed_args.id) - - msg = '{ent} with id {ent_id} was deleted\n' - - self.app.stdout.write( - msg.format( - ent=self.entity_name.capitalize(), - ent_id=parsed_args.id)) - - -@six.add_metaclass(abc.ABCMeta) -class BaseTasksExecuteCommand(BaseCommand): - - def get_parser(self, prog_name): - parser = super(BaseTasksExecuteCommand, self).get_parser(prog_name) - - parser.add_argument( - '-e', '--env', - type=int, - required=True, - help='Id of the environment' - ) - parser.add_argument( - '--force', - action="store_true", - default=False, - help='Force run all deployment tasks without skipping.') - - parser.add_argument( - '--trace', - action="store_true", - default=False, - help='Enable debugging mode in tasks executor.' - ) - parser.add_argument( - '--format', - choices=['json', 'yaml'], - help='Select output format, by default text message will produce.' - ) - - mode_group = parser.add_mutually_exclusive_group() - mode_group.add_argument( - '--dry-run', - action="store_true", - default=False, - help='Specifies to dry-run a deployment by configuring ' - 'task executor to dump the deployment graph to a dot file.' - ) - mode_group.add_argument( - '--noop', - action="store_true", - default=False, - help='Specifies noop-run deployment configuring tasks executor ' - 'to run all tasks in noop mode. ' - 'Execution result summary can be got via history of tasks.') - - return parser - - def take_action(self, parsed_args): - task = self.client.execute( - env_id=parsed_args.env, - dry_run=parsed_args.dry_run, - noop_run=parsed_args.noop, - force=parsed_args.force, - debug=parsed_args.trace, - **self.get_options(parsed_args) - ) - if parsed_args.format: - msg = Serializer(parsed_args.format).serialize(task.data) + '\n' - else: - msg = ( - 'Deployment task with id {0} for the environment {1} ' - 'has been started.\n' - .format(task.data['id'], task.data['cluster']) - ) - self.app.stdout.write(msg) - - def get_options(self, parsed_args): - """Produce additional options from cmdline arguments.""" - raise NotImplementedError diff --git a/fuelclient/commands/environment.py b/fuelclient/commands/environment.py deleted file mode 100644 index aa80625b..00000000 --- a/fuelclient/commands/environment.py +++ /dev/null @@ -1,933 +0,0 @@ -# Copyright 2015 Mirantis, 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 abc -import argparse -import functools -import os -import shutil - -import six - -from cliff import show -from oslo_utils import fileutils - -from fuelclient.cli import error -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class EnvMixIn(object): - entity_name = 'environment' - - supported_file_formats = ('json', 'yaml') - allowed_attr_types = ('network', 'settings') - - @staticmethod - def source_dir(directory): - """Check that the source directory exists and is readable. - - :param directory: Path to source directory - :type directory: str - :return: Absolute path to source directory - :rtype: str - """ - path = os.path.abspath(directory) - if not os.path.isdir(path): - raise argparse.ArgumentTypeError( - '"{0}" is not a directory.'.format(path)) - if not os.access(path, os.R_OK): - raise argparse.ArgumentTypeError( - 'directory "{0}" is not readable'.format(path)) - return path - - @staticmethod - def destination_dir(directory): - """Check that the destination directory exists and is writable. - - :param directory: Path to destination directory - :type directory: str - :return: Absolute path to destination directory - :rtype: str - """ - path = os.path.abspath(directory) - if not os.path.isdir(path): - raise argparse.ArgumentTypeError( - '"{0}" is not a directory.'.format(path)) - if not os.access(path, os.W_OK): - raise argparse.ArgumentTypeError( - 'directory "{0}" is not writable'.format(path)) - return path - - -@six.add_metaclass(abc.ABCMeta) -class BaseUploadCommand(EnvMixIn, base.BaseCommand): - - @abc.abstractproperty - def uploader(self): - pass - - @abc.abstractproperty - def attribute(self): - pass - - def get_parser(self, prog_name): - parser = super(BaseUploadCommand, self).get_parser(prog_name) - parser.add_argument('id', - type=int, - help='Id of environment.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized ' - '{}.'.format(self.attribute)) - parser.add_argument('-d', - '--directory', - required=False, - default=os.curdir, - help='Source directory. Defaults to the ' - 'current directory.') - - return parser - - def take_action(self, parsed_args): - directory = parsed_args.directory - file_path = self.get_attributes_path(self.attribute, - parsed_args.format, - parsed_args.id, - directory) - try: - with open(file_path, 'r') as stream: - attribute = data_utils.safe_load(parsed_args.format, stream) - except (IOError, OSError): - msg = 'Could not read configuration of {} at {}.' - raise error.InvalidFileException(msg.format(self.attribute, - file_path)) - - self.uploader(parsed_args.id, attribute) - - msg = ('Configuration of {t} for the environment with id ' - '{env} was loaded from {path}\n') - - self.app.stdout.write(msg.format(t=self.attribute, - env=parsed_args.id, - path=file_path)) - - -@six.add_metaclass(abc.ABCMeta) -class BaseDownloadCommand(EnvMixIn, base.BaseCommand): - - @abc.abstractproperty - def downloader(self): - pass - - @abc.abstractproperty - def attribute(self): - pass - - def get_parser(self, prog_name): - parser = super(BaseDownloadCommand, self).get_parser(prog_name) - parser.add_argument('id', - type=int, - help='Id of an environment.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized ' - '{}.'.format(self.attribute)) - parser.add_argument('-d', - '--directory', - required=False, - default=os.curdir, - help='Destination directory. Defaults to the ' - 'current directory.') - - return parser - - def take_action(self, parsed_args): - directory = parsed_args.directory or os.curdir - attributes = self.downloader(parsed_args.id) - - file_path = self.get_attributes_path(self.attribute, - parsed_args.format, - parsed_args.id, - directory) - - try: - fileutils.ensure_tree(os.path.dirname(file_path)) - fileutils.delete_if_exists(file_path) - - with open(file_path, 'w') as stream: - data_utils.safe_dump(parsed_args.format, stream, attributes) - except (IOError, OSError): - msg = 'Could not store configuration of {} at {}.' - raise error.InvalidFileException(msg.format(self.attribute, - file_path)) - - msg = ('Configuration of {t} for the environment with id ' - '{env} was stored in {path}\n') - self.app.stdout.write(msg.format(t=self.attribute, - env=parsed_args.id, - path=file_path)) - - -class EnvList(EnvMixIn, base.BaseListCommand): - """Show list of all available environments.""" - - columns = ("id", - "status", - "name", - "release_id") - - -class EnvShow(EnvMixIn, base.BaseShowCommand): - """Show info about environment with given id.""" - columns = ("id", - "status", - "fuel_version", - "name", - "release_id", - "is_customized", - "changes") - - -class EnvCreate(EnvMixIn, base.BaseShowCommand): - """Creates environment with given attributes.""" - - columns = EnvShow.columns - - def get_parser(self, prog_name): - # Avoid adding id argument by BaseShowCommand - parser = show.ShowOne.get_parser(self, prog_name) - - parser.add_argument( - 'name', - type=str, - help='Name of the new environment' - ) - - parser.add_argument('-r', - '--release', - type=int, - required=True, - help='Id of the release for which will ' - 'be deployed') - - parser.add_argument('-nst', - '--net-segmentation-type', - type=str, - choices=['vlan', 'gre', 'tun'], - dest='nst', - default='vlan', - help='Network segmentation type.\n' - 'WARNING: GRE network segmentation type ' - 'is deprecated since 7.0 release.') - - return parser - - def take_action(self, parsed_args): - if parsed_args.nst == 'gre': - self.app.stderr.write('WARNING: GRE network segmentation type is ' - 'deprecated since 7.0 release') - - new_env = self.client.create(name=parsed_args.name, - release_id=parsed_args.release, - net_segment_type=parsed_args.nst) - - new_env = data_utils.get_display_data_single(self.columns, new_env) - - return (self.columns, new_env) - - -class EnvDelete(EnvMixIn, base.BaseDeleteCommand): - """Delete environment with given id.""" - - def get_parser(self, prog_name): - parser = super(EnvDelete, self).get_parser(prog_name) - - parser.add_argument('-f', - '--force', - action='store_true', - help='Force-delete the environment.') - - return parser - - def take_action(self, parsed_args): - env = self.client.get_by_id(parsed_args.id) - - if env['status'] == 'operational' and not parsed_args.force: - self.app.stdout.write("Deleting an operational environment is a " - "dangerous operation.\n" - "Please use --force to bypass this message.") - return - - return super(EnvDelete, self).take_action(parsed_args) - - -class EnvUpdate(EnvMixIn, base.BaseShowCommand): - """Change given attributes for an environment.""" - - columns = EnvShow.columns - - def get_parser(self, prog_name): - # Avoid adding id argument by BaseShowCommand - parser = show.ShowOne.get_parser(self, prog_name) - - parser.add_argument('id', - type=int, - help='Id of the nailgun entity to be processed.') - - parser.add_argument('-n', - '--name', - type=str, - dest='name', - default=None, - help='New name for environment') - - return parser - - def take_action(self, parsed_args): - updates = {} - for attr in self.client._updatable_attributes: - if getattr(parsed_args, attr, None): - updates[attr] = getattr(parsed_args, attr) - - updated_env = self.client.update(environment_id=parsed_args.id, - **updates) - updated_env = data_utils.get_display_data_single(self.columns, - updated_env) - - return (self.columns, updated_env) - - -class EnvReset(EnvMixIn, base.BaseCommand): - """Reset deployed environment.""" - - def get_parser(self, prog_name): - parser = super(EnvReset, self).get_parser(prog_name) - - parser.add_argument('id', - type=int, - help='Id of the environment to reset.') - parser.add_argument('-f', - '--force', - action='store_true', - help='Force reset environment.') - - return parser - - def take_action(self, parsed_args): - result = self.client.reset(parsed_args.id, force=parsed_args.force) - - msg = ('Reset task with id {t} for the environment {e} ' - 'has been started.\n'.format(t=result.data['id'], - e=result.data['cluster'])) - - self.app.stdout.write(msg) - - -class EnvStopDeploy(EnvMixIn, base.BaseCommand): - """Stop deployment process for specific environment.""" - - def get_parser(self, prog_name): - parser = super(EnvStopDeploy, self).get_parser(prog_name) - - parser.add_argument('id', - type=int, - help='Id of the environment to stop deployment.') - - return parser - - def take_action(self, parsed_args): - result = self.client.stop(parsed_args.id) - - msg = ('Stop deployment task with id {t} for the environment ' - '{e} has been started.\n'.format(t=result.data['id'], - e=result.data['cluster'])) - self.app.stdout.write(msg) - - -class EnvAddNodes(EnvMixIn, base.BaseCommand): - """Adds nodes to an environment with the specified roles.""" - - def get_parser(self, prog_name): - - parser = super(EnvAddNodes, self).get_parser(prog_name) - - parser.add_argument('-e', - '--env', - type=int, - required=True, - help='Id of the environment to add nodes to') - - parser.add_argument('-n', - '--nodes', - type=int, - nargs='+', - required=True, - help='Ids of the nodes to add.') - - parser.add_argument('-r', - '--roles', - type=str, - nargs='+', - required=True, - help='Target roles of the nodes.') - - return parser - - def take_action(self, parsed_args): - env_id = parsed_args.env - - self.client.add_nodes(environment_id=env_id, - nodes=parsed_args.nodes, - roles=parsed_args.roles) - - msg = 'Nodes {n} were added to the environment {e} with roles {r}\n' - self.app.stdout.write(msg.format(n=parsed_args.nodes, - e=parsed_args.env, - r=parsed_args.roles)) - - -class EnvRemoveNodes(EnvMixIn, base.BaseCommand): - """Removes nodes from an environment.""" - - def get_parser(self, prog_name): - - parser = super(EnvRemoveNodes, self).get_parser(prog_name) - - parser.add_argument('-e', - '--env', - type=int, - required=True, - help='Id of the environment to remove nodes from') - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-n', - '--nodes', - type=int, - nargs='+', - help='Ids of the nodes to remove.') - - group.add_argument('--nodes-all', - action='store_true', - help='Remove all nodes from environment') - - return parser - - def take_action(self, parsed_args): - nodes = None if parsed_args.nodes_all else parsed_args.nodes - self.client.remove_nodes(environment_id=parsed_args.env, - nodes=nodes) - - msg = 'Nodes were removed from the environment with id={e}\n'.format( - e=parsed_args.env) - - self.app.stdout.write(msg) - - -class EnvDeploy(EnvMixIn, base.BaseCommand): - """Deploys changes on the specified environment.""" - - def get_parser(self, prog_name): - parser = super(EnvDeploy, self).get_parser(prog_name) - - parser.add_argument('id', - type=int, - help='Id of the environment to be deployed.') - - dry_run_help_string = 'Specifies to dry-run a deployment by' \ - 'configuring task executor to dump the' \ - 'deployment graph to a dot file.' \ - 'Store cluster settings and serialized ' \ - 'data in the db and ask the task executor ' \ - 'to dump the resulting graph into a dot file' - noop_run_help_string = 'Specifies noop-run deployment ' \ - 'configuring tasks executor to run ' \ - 'puppet and shell tasks in noop mode and ' \ - 'skip all other. Stores noop-run result ' \ - 'summary in nailgun database' - parser.add_argument( - '-d', '--dry-run', dest="dry_run", - action='store_true', help=dry_run_help_string) - parser.add_argument( - '--noop', dest="noop_run", - action='store_true', help=noop_run_help_string) - - return parser - - def take_action(self, parsed_args): - task_id = self.client.deploy_changes(parsed_args.id, - dry_run=parsed_args.dry_run, - noop_run=parsed_args.noop_run) - - msg = 'Deployment task with id {t} for the environment {e} '\ - 'has been started.\n'.format(t=task_id, e=parsed_args.id) - - self.app.stdout.write(msg) - - -class EnvRedeploy(EnvDeploy): - """Redeploys changes on the specified environment.""" - - def take_action(self, parsed_args): - task_id = self.client.redeploy_changes(parsed_args.id, - dry_run=parsed_args.dry_run, - noop_run=parsed_args.noop_run) - - msg = 'Deployment task with id {t} for the environment {e} '\ - 'has been started.\n'.format(t=task_id, e=parsed_args.id) - - self.app.stdout.write(msg) - - -class EnvProvisionNodes(EnvMixIn, base.BaseCommand): - """Provision specified nodes for a specified environment.""" - - def get_parser(self, prog_name): - parser = super(EnvProvisionNodes, self).get_parser(prog_name) - - parser.add_argument('-e', - '--env', - required=True, - type=int, - help='Id of the environment.') - parser.add_argument('-n', - '--nodes', - required=True, - type=int, - nargs='+', - help='Ids of nodes to provision.') - - return parser - - def take_action(self, parsed_args): - node_ids = parsed_args.nodes - task = self.client.provision_nodes(parsed_args.env, node_ids) - - msg = ('Provisioning task with id {t} for the nodes {n} ' - 'within the environment {e} has been ' - 'started.\n').format(t=task['id'], - e=parsed_args.env, - n=', '.join(str(i) for i in node_ids)) - - self.app.stdout.write(msg) - - -class EnvDeployNodes(EnvMixIn, base.BaseCommand): - """Deploy specified nodes for a specified environment.""" - - def get_parser(self, prog_name): - parser = super(EnvDeployNodes, self).get_parser(prog_name) - - parser.add_argument('-e', - '--env', - required=True, - type=int, - help='Id of the environment.') - parser.add_argument('-n', - '--nodes', - required=True, - type=int, - nargs='+', - help='Ids of nodes to deploy.') - parser.add_argument('-f', - '--force', - action='store_true', - help='Force deploy nodes.') - - noop_run_help_string = 'Specifies noop-run deployment ' \ - 'configuring tasks executor to run ' \ - 'puppet and shell tasks in noop mode and ' \ - 'skip all other. Stores noop-run result ' \ - 'summary in nailgun database' - parser.add_argument('--noop', dest="noop_run", action='store_true', - help=noop_run_help_string) - return parser - - def take_action(self, parsed_args): - node_ids = parsed_args.nodes - task = self.client.deploy_nodes(parsed_args.env, node_ids, - force=parsed_args.force, - noop_run=parsed_args.noop_run) - - msg = ('Deployment task with id {t} for the nodes {n} within ' - 'the environment {e} has been ' - 'started.\n').format(t=task['id'], - e=parsed_args.env, - n=', '.join(str(i) for i in node_ids)) - - self.app.stdout.write(msg) - - -class EnvSpawnVms(EnvMixIn, base.BaseCommand): - """Provision specified environment.""" - - def get_parser(self, prog_name): - parser = super(EnvSpawnVms, self).get_parser(prog_name) - - parser.add_argument('id', - type=int, - help='Id of the environment to be provision.') - - return parser - - def take_action(self, parsed_args): - return self.client.spawn_vms(parsed_args.id) - - -class EnvNetworkVerify(EnvMixIn, base.BaseCommand): - """Run network verification for specified environment.""" - - def get_parser(self, prog_name): - parser = super(EnvNetworkVerify, self).get_parser(prog_name) - - parser.add_argument('id', - type=int, - help='Id of the environment to verify network.') - - return parser - - def take_action(self, parsed_args): - task = self.client.verify_network(parsed_args.id) - msg = 'Network verification task with id {t} for the environment {e} '\ - 'has been started.\n'.format(t=task['id'], e=parsed_args.id) - - self.app.stdout.write(msg) - - -class EnvNetworkUpload(BaseUploadCommand): - """Upload network configuration and apply it to an environment.""" - - attribute = 'network' - - @property - def uploader(self): - return self.client.set_network_configuration - - -class EnvNetworkDownload(BaseDownloadCommand): - """Download and store network configuration of an environment.""" - - attribute = 'network' - - @property - def downloader(self): - return self.client.get_network_configuration - - -class EnvSettingsUpload(BaseUploadCommand): - """Upload and apply environment settings.""" - - attribute = 'settings' - - @property - def uploader(self): - return functools.partial(self.client.set_settings, - force=self.force_flag) - - def get_parser(self, prog_name): - parser = super(EnvSettingsUpload, self).get_parser(prog_name) - parser.add_argument('--force', - action='store_true', - help='Force applying the settings.') - - return parser - - def take_action(self, parsed_args): - self.force_flag = parsed_args.force - - super(EnvSettingsUpload, self).take_action(parsed_args) - - -class EnvSettingsDownload(BaseDownloadCommand): - """Download and store environment settings.""" - - attribute = 'settings' - - @property - def downloader(self): - return self.client.get_settings - - -class FactsMixIn(object): - - @staticmethod - def _get_fact_dir(env_id, fact_type, directory): - return os.path.join(directory, "{0}_{1}".format(fact_type, env_id)) - - @staticmethod - def _read_deployment_facts_from_file(directory, file_format): - return list(six.moves.map( - lambda f: data_utils.read_from_file(f), - [os.path.join(directory, file_name) - for file_name in os.listdir(directory) - if file_format == os.path.splitext(file_name)[1].lstrip('.')] - )) - - @staticmethod - def _read_provisioning_facts_from_file(directory, file_format): - node_facts = list(six.moves.map( - lambda f: data_utils.read_from_file(f), - [os.path.join(directory, file_name) - for file_name in os.listdir(directory) - if file_format == os.path.splitext(file_name)[1].lstrip('.') - and 'engine' != os.path.splitext(file_name)[0]] - )) - - engine_facts = None - engine_file = os.path.join(directory, - "{}.{}".format('engine', file_format)) - if os.path.lexists(engine_file): - engine_facts = data_utils.read_from_file(engine_file) - - return {'engine': engine_facts, 'nodes': node_facts} - - @staticmethod - def _write_deployment_facts_to_file(facts, directory, file_format): - # from 9.0 the deployment info is serialized only per node - for _fact in facts: - file_name = "{role}_{uid}." if 'role' in _fact else "{uid}." - file_name += file_format - data_utils.write_to_file( - os.path.join(directory, file_name.format(**_fact)), - _fact) - - @staticmethod - def _write_provisioning_facts_to_file(facts, directory, file_format): - file_name = "{uid}." - file_name += file_format - data_utils.write_to_file( - os.path.join(directory, file_name.format(uid='engine')), - facts['engine']) - - for _fact in facts['nodes']: - data_utils.write_to_file( - os.path.join(directory, file_name.format(**_fact)), - _fact) - - def download(self, env_id, fact_type, destination_dir, file_format, - nodes=None, default=False, split=None): - facts = self.client.download_facts( - env_id, fact_type, nodes=nodes, default=default, split=split) - - facts_dir = self._get_fact_dir(env_id, fact_type, destination_dir) - if os.path.exists(facts_dir): - shutil.rmtree(facts_dir) - os.makedirs(facts_dir) - - getattr(self, "_write_{0}_facts_to_file".format(fact_type))( - facts, facts_dir, file_format) - - return facts_dir - - def upload(self, env_id, fact_type, source_dir, file_format): - facts_dir = self._get_fact_dir(env_id, fact_type, source_dir) - facts = getattr(self, "_read_{0}_facts_from_file".format(fact_type))( - facts_dir, file_format) - - if not facts \ - or isinstance(facts, dict) and not six.moves.reduce( - lambda a, b: a or b, facts.values()): - raise error.ServerDataException( - "There are no {} facts for this environment!".format( - fact_type)) - - return self.client.upload_facts(env_id, fact_type, facts) - - -class BaseEnvFactsDelete(EnvMixIn, base.BaseCommand): - """Delete current various facts for orchestrator.""" - - fact_type = '' - - def get_parser(self, prog_name): - parser = super(BaseEnvFactsDelete, self).get_parser(prog_name) - - parser.add_argument( - 'id', - type=int, - help='ID of the environment') - - return parser - - def take_action(self, parsed_args): - self.client.delete_facts(parsed_args.id, self.fact_type) - self.app.stdout.write( - "{0} facts for the environment {1} were deleted " - "successfully.\n".format(self.fact_type.capitalize(), - parsed_args.id) - ) - - -class EnvDeploymentFactsDelete(BaseEnvFactsDelete): - """Delete current deployment facts.""" - - fact_type = 'deployment' - - -class EnvProvisioningFactsDelete(BaseEnvFactsDelete): - """Delete current provisioning facts.""" - - fact_type = 'provisioning' - - -class BaseEnvFactsDownload(FactsMixIn, EnvMixIn, base.BaseCommand): - """Download various facts for orchestrator.""" - - fact_type = '' - fact_default = False - - def get_parser(self, prog_name): - parser = super(BaseEnvFactsDownload, self).get_parser(prog_name) - - parser.add_argument( - '-e', '--env', - type=int, - required=True, - help='ID of the environment') - - parser.add_argument( - '-d', '--directory', - type=self.destination_dir, - default=os.path.curdir, - help='Path to directory to save {} facts. ' - 'Defaults to the current directory'.format(self.fact_type)) - - parser.add_argument( - '-n', '--nodes', - type=int, - nargs='+', - help='Get {} facts for nodes with given IDs'.format( - self.fact_type)) - - parser.add_argument( - '-f', '--format', - choices=self.supported_file_formats, - required=True, - help='Format of serialized {} facts'.format(self.fact_type)) - - parser.add_argument( - '--no-split', - action='store_false', - dest='split', - default=True, - help='Do not split deployment info for node and cluster parts.' - ) - - return parser - - def take_action(self, parsed_args): - facts_dir = self.download( - parsed_args.env, - self.fact_type, - parsed_args.directory, - parsed_args.format, - nodes=parsed_args.nodes, - default=self.fact_default, - split=parsed_args.split - ) - self.app.stdout.write( - "{0} {1} facts for the environment {2} " - "were downloaded to {3}\n".format( - 'Default' if self.fact_default else 'User-defined', - self.fact_type, - parsed_args.env, - facts_dir) - ) - - -class EnvDeploymentFactsDownload(BaseEnvFactsDownload): - """Download the user-defined deployment facts.""" - - fact_type = 'deployment' - fact_default = False - - -class EnvDeploymentFactsGetDefault(BaseEnvFactsDownload): - """Download the default deployment facts.""" - - fact_type = 'deployment' - fact_default = True - - -class EnvProvisioningFactsDownload(BaseEnvFactsDownload): - """Download the user-defined provisioning facts.""" - - fact_type = 'provisioning' - fact_default = False - - -class EnvProvisioningFactsGetDefault(BaseEnvFactsDownload): - """Download the default provisioning facts.""" - - fact_type = 'provisioning' - fact_default = True - - -class BaseEnvFactsUpload(FactsMixIn, EnvMixIn, base.BaseCommand): - """Upload various facts for orchestrator.""" - - fact_type = '' - - def get_parser(self, prog_name): - parser = super(BaseEnvFactsUpload, self).get_parser(prog_name) - - parser.add_argument( - '-e', '--env', - type=int, - required=True, - help='ID of the environment') - - parser.add_argument( - '-d', '--directory', - type=self.source_dir, - default=os.path.curdir, - help='Path to directory to read {} facts. ' - 'Defaults to the current directory'.format(self.fact_type)) - - parser.add_argument( - '-f', '--format', - choices=self.supported_file_formats, - required=True, - help='Format of serialized {} facts'.format(self.fact_type)) - - return parser - - def take_action(self, parsed_args): - self.upload( - parsed_args.env, - self.fact_type, - parsed_args.directory, - parsed_args.format - ) - self.app.stdout.write( - "{0} facts for the environment {1} were uploaded " - "successfully.\n".format(self.fact_type.capitalize(), - parsed_args.env) - ) - - -class EnvDeploymentFactsUpload(BaseEnvFactsUpload): - """Upload deployment facts.""" - - fact_type = 'deployment' - - -class EnvProvisioningFactsUpload(BaseEnvFactsUpload): - """Upload provisioning facts.""" - - fact_type = 'provisioning' diff --git a/fuelclient/commands/extension.py b/fuelclient/commands/extension.py deleted file mode 100644 index 9a59afad..00000000 --- a/fuelclient/commands/extension.py +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from cliff import show - -from fuelclient.commands import base - - -class ExtensionMixIn(object): - entity_name = 'extension' - - -class ExtensionList(ExtensionMixIn, base.BaseListCommand): - """Show list of all available extensions.""" - - columns = ("name", - "version", - "description", - "provides") - default_sorting_by = ["name"] - - -class EnvExtensionShow(ExtensionMixIn, base.BaseShowCommand): - """Show list of enabled extensions for environment with given id.""" - - columns = ("extensions", ) - - def get_parser(self, prog_name): - # Avoid adding id argument by BaseShowCommand - # Because it adds 'id' with wrong help message for this class - parser = show.ShowOne.get_parser(self, prog_name) - - parser.add_argument('id', type=int, help='Id of the environment.') - - return parser - - -class EnvExtensionEnable(ExtensionMixIn, base.BaseCommand): - """Enable specified extensions for environment with given id.""" - - def get_parser(self, prog_name): - parser = super(EnvExtensionEnable, self).get_parser(prog_name) - - parser.add_argument('id', type=int, help='Id of the environment.') - parser.add_argument('-E', - '--extensions', - required=True, - nargs='+', - help='Names of extensions to enable.') - - return parser - - def take_action(self, parsed_args): - self.client.enable_extensions(parsed_args.id, parsed_args.extensions) - - msg = ('The following extensions: {e} have been enabled for ' - 'the environment with id {id}.\n'.format( - e=', '.join(parsed_args.extensions), id=parsed_args.id)) - - self.app.stdout.write(msg) - - -class EnvExtensionDisable(ExtensionMixIn, base.BaseCommand): - """Disable specified extensions for environment with given id.""" - - def get_parser(self, prog_name): - parser = super(EnvExtensionDisable, self).get_parser(prog_name) - - parser.add_argument('id', type=int, help='Id of the environment.') - parser.add_argument('-E', - '--extensions', - required=True, - nargs='+', - help='Names of extensions to disable.') - - return parser - - def take_action(self, parsed_args): - self.client.disable_extensions(parsed_args.id, parsed_args.extensions) - - msg = ('The following extensions: {e} have been disabled for ' - 'the environment with id {id}.\n'.format( - e=', '.join(parsed_args.extensions), id=parsed_args.id)) - - self.app.stdout.write(msg) diff --git a/fuelclient/commands/fuelversion.py b/fuelclient/commands/fuelversion.py deleted file mode 100644 index 2ae0c8b5..00000000 --- a/fuelclient/commands/fuelversion.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from cliff import show - -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class FuelVersion(show.ShowOne, base.BaseCommand): - """Show the version of Fuel.""" - - entity_name = 'fuel-version' - columns = ('api', - 'auth_required', - 'feature_groups', - 'openstack_version', - 'release') - - def take_action(self, parsed_args): - data = self.client.get_all() - data = data_utils.get_display_data_single(self.columns, data) - - return (self.columns, data) diff --git a/fuelclient/commands/graph.py b/fuelclient/commands/graph.py deleted file mode 100644 index 986e2f16..00000000 --- a/fuelclient/commands/graph.py +++ /dev/null @@ -1,414 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 - -from fuelclient.cli import error -from fuelclient.cli.serializers import Serializer -from fuelclient.commands import base -from fuelclient.common import data_utils -from fuelclient.utils import iterfiles - - -class FileMethodsMixin(object): - @classmethod - def check_file_path(cls, file_path): - if not os.path.exists(file_path): - raise error.InvalidFileException( - "File '{0}' doesn't exist.".format(file_path)) - - @classmethod - def check_dir(cls, directory): - if not os.path.exists(directory): - raise error.InvalidDirectoryException( - "Directory '{0}' doesn't exist.".format(directory)) - if not os.path.isdir(directory): - raise error.InvalidDirectoryException( - "Error: '{0}' is not a directory.".format(directory)) - - -class GraphUpload(base.BaseCommand, FileMethodsMixin): - """Upload deployment graph configuration.""" - entity_name = 'graph' - - @classmethod - def read_data_from_file(cls, file_path=None, serializer=None): - """Read graph data from given path. - - :param file_path: path - :type file_path: str - :param serializer: serializer object - :type serializer: object - :return: data - :rtype: list|object - """ - cls.check_file_path(file_path) - return (serializer or Serializer()).read_from_full_path(file_path) - - @classmethod - def read_data_from_dir(cls, dir_path=None, serializer=None): - """Read graph data from directory. - - :param dir_path: path - :type dir_path: str - :param serializer: serializer object - :type serializer: object - :return: data - :rtype: list|object - """ - cls.check_dir(dir_path) - serializer = serializer or Serializer() - - metadata_filepath = os.path.join(dir_path, 'metadata.yaml') - if os.path.exists(metadata_filepath): - data = serializer.read_from_full_path(metadata_filepath) - else: - data = {} - - tasks = [] - for file_name in iterfiles(dir_path, 'tasks.yaml'): - task_data = serializer.read_from_full_path(file_name) - if task_data: - tasks.extend(task_data) - - if tasks: - data['tasks'] = tasks - - if not data: - msg = ("Nothing to upload. Check if at least one 'tasks.yaml' " - "file is not empty and exists in '{path}' directory " - "path".format(path=dir_path)) - raise error.ActionException(msg) - return data - - def get_parser(self, prog_name): - parser = super(GraphUpload, self).get_parser(prog_name) - graph_class = parser.add_mutually_exclusive_group(required=True) - - graph_class.add_argument('-e', - '--env', - type=int, - required=False, - help='Id of the environment') - graph_class.add_argument('-r', - '--release', - type=int, - required=False, - help='Id of the release') - graph_class.add_argument('-p', - '--plugin', - type=int, - required=False, - help='Id of the plugin') - - parser.add_argument('-t', - '--graph-type', - required=True, - help='Type of the deployment graph') - - graph_source = parser.add_mutually_exclusive_group(required=True) - graph_source.add_argument( - '-f', - '--file', - default=None, - help='YAML file that contains deployment graph data.' - ) - graph_source.add_argument( - '-d', - '--dir', - default=None, - help='The directory that includes tasks.yaml and metadata.yaml.' - ) - return parser - - def take_action(self, args): - parameters_to_graph_class = ( - ('env', 'clusters'), - ('release', 'releases'), - ('plugin', 'plugins'), - ) - - if args.file: - data = self.read_data_from_file(args.file) - else: - data = self.read_data_from_dir(args.dir) - - for parameter, graph_class in parameters_to_graph_class: - model_id = getattr(args, parameter) - if model_id: - self.client.upload( - data=data, - related_model=graph_class, - related_id=model_id, - graph_type=args.graph_type - ) - break - - self.app.stdout.write("Deployment graph was successfully uploaded.\n") - - -class GraphExecute(base.BaseTasksExecuteCommand): - """Start deployment with given graph type.""" - entity_name = 'graph' - - def get_parser(self, prog_name): - parser = super(GraphExecute, self).get_parser(prog_name) - parser.add_argument( - '-t', - '--graph-types', - nargs='+', - required=True, - help='Types of the deployment graph in order of execution' - ) - parser.add_argument( - '-n', - '--nodes', - type=int, - nargs='+', - help='Ids of the nodes to use for deployment.' - ) - parser.add_argument( - '-T', - '--task-names', - nargs='+', - help='List of deployment tasks to run.' - ) - parser.add_argument('-S', - '--subgraphs', - type=str, - nargs='+', - required=False, - help='List of subgraphs to execute' - 'Format is: ' - '[[/]]\ - [:/[]]') - return parser - - def get_options(self, parsed_args): - return { - 'graph_types': parsed_args.graph_types, - 'nodes': parsed_args.nodes, - 'task_names': parsed_args.task_names, - 'subgraphs': parsed_args.subgraphs - } - - -class GraphDownload(base.BaseCommand): - """Download deployment graph configuration.""" - entity_name = 'graph' - supported_file_formats = ('json', 'yaml') - - def get_parser(self, prog_name): - parser = super(GraphDownload, self).get_parser(prog_name) - tasks_level = parser.add_mutually_exclusive_group(required=True) - parser.add_argument('-e', - '--env', - type=int, - required=True, - help='Id of the environment') - - tasks_level.add_argument('-a', - '--all', - action="store_true", - required=False, - default=False, - help='Download merged graph for the ' - 'environment') - tasks_level.add_argument('-c', - '--cluster', - action="store_true", - required=False, - default=False, - help='Download cluster-specific tasks') - tasks_level.add_argument('-p', - '--plugins', - action="store_true", - required=False, - default=False, - help='Download plugins-specific tasks') - tasks_level.add_argument('-r', - '--release', - action="store_true", - required=False, - default=False, - help='Download release-specific tasks') - - parser.add_argument('-t', - '--graph-type', - type=str, - default=None, - required=False, - help='Graph type string') - parser.add_argument('-f', - '--file', - type=str, - required=False, - default=None, - help='File in {} format that contains tasks ' - 'data.'.format(self.supported_file_formats)) - parser.add_argument('--format', - required=False, - choices=self.supported_file_formats, - default='yaml', - help='Format of serialized tasks data. ' - 'Defaults to YAML.') - return parser - - @classmethod - def get_default_tasks_data_path(cls, env_id, task_level_name, file_format): - return os.path.join( - os.path.abspath(os.curdir), - '{}_graph_{}.{}'.format(task_level_name, env_id, file_format) - ) - - @classmethod - def write_tasks_to_file(cls, tasks_data, serializer, file_path): - return serializer.write_to_full_path(file_path, tasks_data) - - def take_action(self, args): - tasks_data = [] - tasks_level_name = '' - for tasks_level_name in ('all', 'cluster', 'release', 'plugins'): - if getattr(args, tasks_level_name): - tasks_data = self.client.download( - env_id=args.env, - level=tasks_level_name, - graph_type=args.graph_type - ) - break - - # write to file - file_path = args.file or self.get_default_tasks_data_path( - args.env, tasks_level_name, args.format) - graph_data_file_path = self.write_tasks_to_file( - tasks_data=tasks_data, - serializer=Serializer(format=args.format), - file_path=file_path) - - self.app.stdout.write( - "Tasks were downloaded to {0}\n".format(graph_data_file_path) - ) - - -class GraphList(base.BaseListCommand): - """List deployment graphs.""" - entity_name = 'graph' - columns = ("id", - "name", - "tasks", - "relations") - - def get_parser(self, prog_name): - parser = super(GraphList, self).get_parser(prog_name) - parser.add_argument( - '-e', - '--env', - type=int, - help='Id of the environment' - ) - parser.add_argument( - '--cluster', - dest='filters', - action='append_const', - const='cluster', - help='Include cluster-specific graphs' - ) - parser.add_argument( - '--plugins', - dest='filters', - action='append_const', - const='plugin', - help='Include plugins-specific graphs' - ) - parser.add_argument( - '--release', - dest='filters', - action='append_const', - const='release', - help='Include release-specific graphs' - ) - return parser - - def take_action(self, args): - data = self.client.list(env_id=args.env, filters=args.filters) - - # make table context applying special formatting to data copy - display_data = [] - for d in data: - d = d.copy() - d.update({ - 'relations': "\n".join( - 'as "{type}" to {model}(ID={model_id})'.format(**r) - for r in d['relations'] - ), - 'tasks': ', '.join(sorted(t['id'] for t in d['tasks'])) - }) - display_data.append(d) - - data = data_utils.get_display_data_multi(self.columns, display_data) - scolumn_ids = [self.columns.index(col) for col in args.sort_columns] - data.sort(key=lambda x: [x[scolumn_id] for scolumn_id in scolumn_ids]) - return self.columns, data - - -class GraphDelete(base.BaseCommand): - """Delete deployment graph.""" - entity_name = 'graph' - - def get_parser(self, prog_name): - parser = super(GraphDelete, self).get_parser(prog_name) - graph_class = parser.add_mutually_exclusive_group(required=True) - graph_class.add_argument('-e', - '--environment', - type=int, - help='Id of the environment') - graph_class.add_argument('-r', - '--release', - type=int, - help='Id of the release') - graph_class.add_argument('-p', - '--plugin', - type=int, - help='Id of the plugin') - parser.add_argument('-t', - '--graph-type', - required=True, - help='Type of the deployment graph') - return parser - - def take_action(self, parsed_args): - parameters_to_graph_class = ( - ('environment', 'clusters'), - ('release', 'releases'), - ('plugin', 'plugins'), - ) - - msg = '' - for parameter, graph_class in parameters_to_graph_class: - model_id = getattr(parsed_args, parameter) - if model_id: - self.client.delete( - related_model=graph_class, - related_id=model_id, - graph_type=parsed_args.graph_type - ) - msg = ("Deployment graph '{0}' for {1} with id {2} was " - "deleted.\n".format(parsed_args.graph_type, - parameter, - model_id)) - break - - self.app.stdout.write(msg) diff --git a/fuelclient/commands/health.py b/fuelclient/commands/health.py deleted file mode 100644 index 64c0b1d5..00000000 --- a/fuelclient/commands/health.py +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 abc -import six - -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class HealthMixIn(object): - - entity_name = 'health' - - -class HealthTestSetsList(HealthMixIn, base.BaseListCommand): - """List of all available test sets for a given environment.""" - - columns = ("id", - "name") - - filters = {'environment_id': 'env'} - - def get_parser(self, prog_name): - parser = super(HealthTestSetsList, self).get_parser(prog_name) - parser.add_argument('-e', - '--env', - type=int, - required=True, - help='Id of the environment.') - return parser - - -class HealthCheckStart(HealthMixIn, base.BaseListCommand): - """Run specified test sets for a given environment.""" - - columns = ("id", - "testset", - "cluster_id") - - def get_parser(self, prog_name): - parser = super(HealthCheckStart, self).get_parser(prog_name) - parser.add_argument('-e', - '--env', - type=int, - required=True, - help='Id of the environment.') - parser.add_argument('--force', - action='store_true', - help='Force run health test sets.') - parser.add_argument('-t', - '--tests', - nargs='+', - help='Name of the test sets to run.') - parser.add_argument('--ostf-username', - default=None, - help='OSTF username.') - parser.add_argument('--ostf-password', - default=None, - help='OSTF password.') - parser.add_argument('--ostf-tenant-name', - default=None, - help='OSTF tenant name.') - return parser - - def take_action(self, parsed_args): - ostf_credentials = {} - if parsed_args.ostf_tenant_name is not None: - ostf_credentials['tenant'] = parsed_args.ostf_tenant_name - if parsed_args.ostf_username is not None: - ostf_credentials['username'] = parsed_args.ostf_username - if parsed_args.ostf_password is not None: - ostf_credentials['password'] = parsed_args.ostf_password - - if not ostf_credentials: - self.app.stdout.write("WARNING: ostf credentials are going to be " - "mandatory in the next release.\n") - - data = self.client.start(parsed_args.env, - ostf_credentials=ostf_credentials, - test_sets=parsed_args.tests, - force=parsed_args.force) - - msg = ("\nHealth check tests for environment with id {0} has been " - "started:\n".format(parsed_args.env)) - self.app.stdout.write(msg) - data = data_utils.get_display_data_multi(self.columns, data) - return self.columns, data - - -@six.add_metaclass(abc.ABCMeta) -class HealthCheckBaseAction(HealthMixIn, base.BaseShowCommand): - """Base class for implementing action over a given test set.""" - - columns = ("id", - "testset", - "cluster_id", - "status") - - @abc.abstractproperty - def action_status(self): - """String with the name of the action.""" - pass - - def take_action(self, parsed_args): - data = self.client.action(parsed_args.id, self.action_status) - - data = data_utils.get_display_data_single(self.columns, data) - return self.columns, data - - -class HealthCheckStop(HealthCheckBaseAction): - """Stop test set with given id.""" - - action_status = "stopped" - - -class HealthCheckRestart(HealthCheckBaseAction): - """Restart test set with given id.""" - - action_status = "restarted" - - -class HealthTestSetsStatusList(HealthMixIn, base.BaseListCommand): - """Show list of statuses of all test sets ever been executed in Fuel.""" - - columns = ("id", - "testset", - "cluster_id", - "status", - "started_at", - "ended_at") - - def get_parser(self, prog_name): - parser = super(HealthTestSetsStatusList, self).get_parser(prog_name) - parser.add_argument('-e', - '--env', - type=int, - help='Id of the environment.') - return parser - - def take_action(self, parsed_args): - data = self.client.get_status_all(parsed_args.env) - - data = data_utils.get_display_data_multi(self.columns, data) - return self.columns, data - - -class HealthTestSetsStatusShow(HealthMixIn, base.BaseShowCommand): - """Show status about a test set with given id.""" - - columns = ("id", - "testset", - "cluster_id", - "status", - "started_at", - "ended_at", - "tests") - - def take_action(self, parsed_args): - data = self.client.get_status_single(parsed_args.id) - - data = data_utils.get_display_data_single(self.columns, data) - return self.columns, data diff --git a/fuelclient/commands/network_group.py b/fuelclient/commands/network_group.py deleted file mode 100644 index 5e16acfb..00000000 --- a/fuelclient/commands/network_group.py +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from cliff import show - -from fuelclient.cli.serializers import Serializer -from fuelclient.commands import base -from fuelclient.common import data_utils - - -_updatable_keys = ( - 'name', 'vlan', 'cidr', 'gateway', 'group_id', 'meta') - - -def get_args_for_update(params, serializer=None): - result = {} - for attr in _updatable_keys: - value = getattr(params, attr, None) - if value is not None: - result[attr] = value - - if 'meta' in result: - serializer = serializer or Serializer.from_params(params) - result['meta'] = serializer.deserialize(result['meta']) - - return result - - -class NetworkGroupMixin(object): - entity_name = 'network-group' - - @staticmethod - def add_parser_arguments(parser, for_update=False): - parser.add_argument( - '-N', '--node-group', - type=int, - required=not for_update, - help='ID of the network group' - ) - - parser.add_argument( - '-C', '--cidr', - type=str, - required=not for_update, - help='CIDR of the network' - ) - - parser.add_argument( - '-V', '--vlan', - type=int, - help='VLAN of the network', - ) - - if not for_update: - parser.add_argument( - '-r', '--release', - type=int, - help='Release ID this network group belongs to' - ) - - parser.add_argument( - '-g', '--gateway', - type=str, - help='Gateway of the network' - ) - - parser.add_argument( - '-m', '--meta', - type=str, - help='Metadata in JSON format to override default network metadata' - ) - - -class NetworkGroupList(NetworkGroupMixin, base.BaseListCommand): - """List all network groups.""" - - columns = ( - 'id', - 'name', - 'vlan_start', - 'cidr', - 'gateway', - 'group_id' - ) - - -class NetworkGroupShow(NetworkGroupMixin, base.BaseShowCommand): - """Show network group.""" - - columns = NetworkGroupList.columns + ('meta',) - - -class NetworkGroupCreate(NetworkGroupMixin, base.BaseShowCommand): - """Create a new network group.""" - - columns = NetworkGroupList.columns - - def get_parser(self, prog_name): - parser = show.ShowOne.get_parser(self, prog_name) - - parser.add_argument( - 'name', - type=str, - help='Name of the new network group' - ) - - self.add_parser_arguments(parser) - - return parser - - def take_action(self, parsed_args): - meta = None - if parsed_args.meta: - serializer = Serializer.from_params(parsed_args) - meta = serializer.deserialize(parsed_args.meta) - - net_group = self.client.create( - name=parsed_args.name, - release=parsed_args.release, - vlan=parsed_args.vlan, - cidr=parsed_args.cidr, - gateway=parsed_args.gateway, - group_id=parsed_args.node_group, - meta=meta) - - net_group = data_utils.get_display_data_single(self.columns, net_group) - return self.columns, net_group - - -class NetworkGroupUpdate(NetworkGroupMixin, base.BaseShowCommand): - """Set parameters for the specified network group.""" - - columns = NetworkGroupList.columns - - def get_parser(self, prog_name): - parser = show.ShowOne.get_parser(self, prog_name) - - parser.add_argument( - 'id', - type=int, - help='ID of the network group to update') - parser.add_argument( - '-n', - '--name', - type=str, - help='New name for network group') - - self.add_parser_arguments(parser, for_update=True) - - return parser - - def take_action(self, parsed_args): - to_update = get_args_for_update(parsed_args) - - network_group = self.client.update(parsed_args.id, **to_update) - network_group = data_utils.get_display_data_single( - self.columns, network_group) - - return self.columns, network_group - - -class NetworkGroupDelete(NetworkGroupMixin, base.BaseDeleteCommand): - """Delete specified network group.""" diff --git a/fuelclient/commands/network_template.py b/fuelclient/commands/network_template.py deleted file mode 100644 index 19efb5b7..00000000 --- a/fuelclient/commands/network_template.py +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.commands import base - - -class NetworkTemplateMixin(object): - - entity_name = 'environment' - - @staticmethod - def add_env_argument(parser): - parser.add_argument( - 'env', - type=int, - help='Id of the environment' - ) - - @staticmethod - def add_dir_argument(parser): - parser.add_argument( - '-d', '--dir', - type=str, - help='Directory for the network template' - ) - - @staticmethod - def add_file_argument(parser): - parser.add_argument( - '-f', '--file', - required=True, - type=str, - help='Yaml file containing the network template' - ) - - -class NetworkTemplateUpload(NetworkTemplateMixin, base.BaseCommand): - """Upload network configuration for specified environment.""" - - def get_parser(self, prog_name): - parser = super(NetworkTemplateUpload, self).get_parser(prog_name) - - self.add_env_argument(parser) - self.add_file_argument(parser) - - return parser - - def take_action(self, parsed_args): - - file_path = self.client.upload_network_template( - parsed_args.env, parsed_args.file) - msg = "Network template {0} has been uploaded.\n".format(file_path) - self.app.stdout.write(msg) - - -class NetworkTemplateDownload(NetworkTemplateMixin, base.BaseCommand): - """Download network configuration for specified environment.""" - - def get_parser(self, prog_name): - parser = super(NetworkTemplateDownload, self).get_parser(prog_name) - - self.add_dir_argument(parser) - self.add_env_argument(parser) - - return parser - - def take_action(self, parsed_args): - file_path = self.client.download_network_template( - parsed_args.env, parsed_args.dir) - - msg = ("Network template configuration for environment with id={0}" - " downloaded to {1}\n").format( - parsed_args.env, file_path) - self.app.stdout.write(msg) - - -class NetworkTemplateDelete(NetworkTemplateMixin, base.BaseCommand): - """Delete the network template of the specified environment.""" - - def get_parser(self, prog_name): - parser = super(NetworkTemplateDelete, self).get_parser(prog_name) - - self.add_env_argument(parser) - - return parser - - def take_action(self, parsed_args): - self.client.delete_network_template(parsed_args.env) - - msg = ("Network template for environment id={0}" - " has been deleted.\n".format(parsed_args.env)) - self.app.stdout.write(msg) diff --git a/fuelclient/commands/node.py b/fuelclient/commands/node.py deleted file mode 100644 index 7b42574a..00000000 --- a/fuelclient/commands/node.py +++ /dev/null @@ -1,609 +0,0 @@ -# Copyright 2015 Mirantis, 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 abc -import collections -import json -import operator -import os - -from oslo_utils import fileutils -import six - -from fuelclient.cli import error -from fuelclient.commands import base -from fuelclient.common import data_utils -from fuelclient import utils - - -class NodeMixIn(object): - entity_name = 'node' - - numa_fields = ( - 'numa_nodes', - 'supported_hugepages', - 'distances') - - supported_file_formats = ('json', 'yaml') - allowed_attr_types = ('attributes', 'disks', 'interfaces') - - @classmethod - def get_numa_topology_info(cls, data): - numa_topology_info = {} - numa_topology = data['meta'].get('numa_topology', {}) - for key in cls.numa_fields: - numa_topology_info[key] = numa_topology.get(key) - return numa_topology_info - - -@six.add_metaclass(abc.ABCMeta) -class BaseUploadCommand(NodeMixIn, base.BaseCommand): - """Base class for uploading attributes of a node.""" - - @abc.abstractproperty - def attribute(self): - """String with the name of the attribute.""" - pass - - @abc.abstractproperty - def uploader(self): - """Callable for uploading data.""" - pass - - def get_parser(self, prog_name): - parser = super(BaseUploadCommand, self).get_parser(prog_name) - parser.add_argument('id', - type=int, - help='Id of a node.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized ' - '{} data.'.format(self.attribute)) - parser.add_argument('-d', - '--directory', - required=False, - default=os.curdir, - help='Source directory. Defaults to ' - 'the current directory.') - - return parser - - def take_action(self, parsed_args): - directory = parsed_args.directory - - file_path = self.get_attributes_path(self.attribute, - parsed_args.format, - parsed_args.id, - directory) - - try: - with open(file_path, 'r') as stream: - attributes = data_utils.safe_load(parsed_args.format, - stream) - self.uploader(parsed_args.id, attributes) - except (OSError, IOError): - msg = 'Could not read configuration of {} at {}.' - raise error.InvalidFileException(msg.format(self.attribute, - file_path)) - - msg = ('Configuration of {t} for node with id ' - '{node} was loaded from {path}\n') - self.app.stdout.write(msg.format(t=self.attribute, - node=parsed_args.id, - path=file_path)) - - -@six.add_metaclass(abc.ABCMeta) -class BaseDownloadCommand(NodeMixIn, base.BaseCommand): - """Base class for downloading attributes of a node.""" - - @abc.abstractproperty - def attribute(self): - """String with the name of the attribute.""" - pass - - @abc.abstractproperty - def downloader(self): - """Callable for downloading data.""" - pass - - def get_parser(self, prog_name): - parser = super(BaseDownloadCommand, self).get_parser(prog_name) - parser.add_argument('id', - type=int, - help='Id of a node.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized ' - '{} data.'.format(self.attribute)) - parser.add_argument('-d', - '--directory', - required=False, - default=os.curdir, - help='Destination directory. Defaults to ' - 'the current directory.') - return parser - - def take_action(self, parsed_args): - directory = parsed_args.directory - attributes = self.downloader(parsed_args.id) - file_path = self.get_attributes_path(self.attribute, - parsed_args.format, - parsed_args.id, - directory) - - try: - fileutils.ensure_tree(os.path.dirname(file_path)) - fileutils.delete_if_exists(file_path) - - with open(file_path, 'w') as stream: - data_utils.safe_dump(parsed_args.format, stream, attributes) - except (OSError, IOError): - msg = 'Could not store configuration of {} at {}.' - raise error.InvalidFileException(msg.format(self.attribute, - file_path)) - - msg = ('Configuration of {t} for node with id ' - '{node} was stored in {path}\n') - self.app.stdout.write(msg.format(t=self.attribute, - node=parsed_args.id, - path=file_path)) - - -class NodeList(NodeMixIn, base.BaseListCommand): - """Show list of all available nodes.""" - - columns = ('id', - 'name', - 'status', - 'os_platform', - 'roles', - 'ip', - 'mac', - 'cluster', - 'platform_name', - 'online') - - filters = { - 'environment_id': 'env', - 'labels': 'labels' - } - - def get_parser(self, prog_name): - parser = super(NodeList, self).get_parser(prog_name) - - parser.add_argument( - '-e', - '--env', - type=int, - help='Show only nodes that are in the specified environment') - - parser.add_argument( - '-l', - '--labels', - type=utils.str_to_unicode, - nargs='+', - help='Show only nodes that have specific labels') - - return parser - - -class NodeShow(NodeMixIn, base.BaseShowCommand): - """Show info about node with given id.""" - - columns = ('id', - 'name', - 'status', - 'os_platform', - 'roles', - 'kernel_params', - 'pending_roles', - 'ip', - 'mac', - 'error_type', - 'pending_addition', - 'hostname', - 'fqdn', - 'platform_name', - 'cluster', - 'online', - 'progress', - 'pending_deletion', - 'group_id', - # TODO(romcheg): network_data mostly never fits the screen - # 'network_data', - 'manufacturer') - columns += NodeMixIn.numa_fields - - def take_action(self, parsed_args): - data = self.client.get_by_id(parsed_args.id) - numa_topology = self.get_numa_topology_info(data) - data.update(numa_topology) - data = data_utils.get_display_data_single(self.columns, data) - return self.columns, data - - -class NodeUpdate(NodeMixIn, base.BaseShowCommand): - """Change given attributes for a node.""" - - columns = NodeShow.columns - - def get_parser(self, prog_name): - parser = super(NodeUpdate, self).get_parser(prog_name) - - parser.add_argument( - '-H', - '--hostname', - type=str, - default=None, - help='New hostname for node') - - parser.add_argument( - '--name', - type=lambda x: x.decode('utf-8') if six.PY2 else x, - default=None, - help='New name for node') - - return parser - - def take_action(self, parsed_args): - updates = {} - for attr in self.client._updatable_attributes: - if getattr(parsed_args, attr, None): - updates[attr] = getattr(parsed_args, attr) - - updated_node = self.client.update( - parsed_args.id, **updates) - numa_topology = self.get_numa_topology_info(updated_node) - updated_node.update(numa_topology) - updated_node = data_utils.get_display_data_single( - self.columns, updated_node) - - return self.columns, updated_node - - -class NodeVmsList(NodeMixIn, base.BaseShowCommand): - """Show list vms for node.""" - - columns = ('vms_conf',) - - def take_action(self, parsed_args): - data = self.client.get_node_vms_conf(parsed_args.id) - data = data_utils.get_display_data_single(self.columns, data) - - return (self.columns, data) - - -class NodeCreateVMsConf(NodeMixIn, base.BaseCommand): - """Create vms config in metadata for selected node.""" - - def get_parser(self, prog_name): - parser = super(NodeCreateVMsConf, self).get_parser(prog_name) - parser.add_argument('id', type=int, - help='Id of the {0}.'.format(self.entity_name)) - parser.add_argument( - '--conf', - type=json.loads, - required=True, - nargs='+', - help='JSONs with VMs configuration', - ) - - return parser - - def take_action(self, parsed_args): - try: - confs = utils.parse_to_list_of_dicts(parsed_args.conf) - except TypeError: - raise error.BadDataException( - 'VM configuration should be a dictionary ' - 'or a list of dictionaries') - data = self.client.node_vms_create(parsed_args.id, confs) - msg = "{0}".format(data) - self.app.stdout.write(msg) - - -class NodeLabelList(NodeMixIn, base.BaseListCommand): - """Show list of all labels.""" - - columns = ( - 'node_id', - 'label_name', - 'label_value') - - @property - def default_sorting_by(self): - return ['node_id'] - - def get_parser(self, prog_name): - parser = super(NodeLabelList, self).get_parser(prog_name) - - parser.add_argument( - '-n', - '--nodes', - nargs='+', - help='Show labels for specific nodes') - - return parser - - def take_action(self, parsed_args): - data = self.client.get_all_labels_for_nodes( - node_ids=parsed_args.nodes) - data = data_utils.get_display_data_multi(self.columns, data) - data = self._sort_data(parsed_args, data) - - return self.columns, data - - -class NodeLabelSet(NodeMixIn, base.BaseCommand): - """Create or update specifc labels on nodes.""" - - def get_parser(self, prog_name): - parser = super(NodeLabelSet, self).get_parser(prog_name) - - parser.add_argument( - '-l', - '--labels', - required=True, - nargs='+', - help='List of labels for create or update') - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument( - '-n', - '--nodes', - nargs='+', - help='Create or update labels only for specific nodes') - group.add_argument( - '--nodes-all', - action='store_true', - help='Create or update labels for all nodes') - - return parser - - def take_action(self, parsed_args): - nodes_ids = None if parsed_args.nodes_all else parsed_args.nodes - data = self.client.set_labels_for_nodes( - labels=parsed_args.labels, node_ids=nodes_ids) - msg = "Labels have been updated on nodes: {0} \n".format( - ','.join(data)) - self.app.stdout.write(msg) - - -class NodeLabelDelete(NodeMixIn, base.BaseCommand): - """Delete specific labels on nodes.""" - - def get_parser(self, prog_name): - parser = super(NodeLabelDelete, self).get_parser(prog_name) - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument( - '-l', - '--labels', - nargs='+', - help='List of labels keys for delete') - group.add_argument( - '--labels-all', - action='store_true', - help='Delete all labels for node') - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument( - '-n', - '--nodes', - nargs='+', - help='Delete labels only for specific nodes') - group.add_argument( - '--nodes-all', - action='store_true', - help='Delete labels for all nodes') - - return parser - - def take_action(self, parsed_args): - nodes_ids = None if parsed_args.nodes_all else parsed_args.nodes - labels = None if parsed_args.labels_all \ - else parsed_args.labels - data = self.client.delete_labels_for_nodes( - labels=labels, node_ids=nodes_ids) - msg = "Labels have been deleted on nodes: {0} \n".format( - ','.join(data)) - self.app.stdout.write(msg) - - -class NodeAttributesDownload(NodeMixIn, base.BaseCommand): - """Download node attributes.""" - - def get_parser(self, prog_name): - parser = super(NodeAttributesDownload, self).get_parser(prog_name) - - parser.add_argument( - 'id', type=int, help='Node ID') - parser.add_argument( - '--dir', type=str, help='Directory to save attributes') - - return parser - - def take_action(self, parsed_args): - file_path = self.client.download_attributes( - parsed_args.id, parsed_args.dir) - self.app.stdout.write( - "Attributes for node {0} were written to {1}" - .format(parsed_args.id, file_path) + os.linesep) - - -class NodeAttributesUpload(NodeMixIn, base.BaseCommand): - """Upload node attributes.""" - - def get_parser(self, prog_name): - parser = super(NodeAttributesUpload, self).get_parser(prog_name) - - parser.add_argument( - 'id', type=int, help='Node ID') - parser.add_argument( - '--dir', type=str, help='Directory to read attributes from') - - return parser - - def take_action(self, parsed_args): - self.client.upload_attributes(parsed_args.id, parsed_args.dir) - self.app.stdout.write( - "Attributes for node {0} were uploaded." - .format(parsed_args.id) + os.linesep) - - -class NodeAnsibleInventory(NodeMixIn, base.BaseCommand): - """Generate ansible inventory file based on the nodes list.""" - - def get_parser(self, prog_name): - parser = super(NodeAnsibleInventory, self).get_parser(prog_name) - - # if this is a required argument, we'll avoid ambiguity of having nodes - # of multiple different clusters in the same inventory file - parser.add_argument( - '-e', - '--env', - type=int, - required=True, - help='Use only nodes that are in the specified environment') - - parser.add_argument( - '-l', - '--labels', - type=utils.str_to_unicode, - nargs='+', - help='Use only nodes that have specific labels') - - return parser - - def take_action(self, parsed_args): - data = self.client.get_all(environment_id=parsed_args.env, - labels=parsed_args.labels) - - nodes_by_role = collections.defaultdict(list) - for node in data: - for role in node['roles']: - nodes_by_role[role].append(node) - - for role, nodes in sorted(nodes_by_role.items()): - self.app.stdout.write(u'[{role}]\n'.format(role=role)) - self.app.stdout.write( - u'\n'.join( - u'{name} ansible_host={ip}'.format(name=node['hostname'], - ip=node['ip']) - for node in sorted(nodes_by_role[role], - key=operator.itemgetter('hostname')) - ) - ) - self.app.stdout.write(u'\n\n') - - -class NodeInterfacesDownload(BaseDownloadCommand): - """Download and store configuration of interfaces for a node to a file.""" - - attribute = 'interfaces' - - @property - def downloader(self): - return self.client.get_interfaces - - -class NodeInterfacesGetDefault(BaseDownloadCommand): - """Download default configuration of interfaces for a node to a file.""" - - attribute = 'interfaces' - - @property - def downloader(self): - return self.client.get_default_interfaces - - -class NodeInterfacesUpload(BaseUploadCommand): - """Upload stored configuration of interfaces for a node from a file.""" - - attribute = 'interfaces' - - @property - def uploader(self): - return self.client.set_interfaces - - -class NodeDisksDownload(BaseDownloadCommand): - """Download and store configuration of disks for a node to a file.""" - - attribute = 'disks' - - @property - def downloader(self): - return self.client.get_disks - - -class NodeDisksGetDefault(BaseDownloadCommand): - """Download default configuration of disks for a node to a file.""" - - attribute = 'disks' - - @property - def downloader(self): - return self.client.get_default_disks - - -class NodeDisksUpload(BaseUploadCommand): - """Upload stored configuration of disks for a node from a file.""" - - attribute = 'disks' - - @property - def uploader(self): - return self.client.set_disks - - -class NodeUndiscover(NodeMixIn, base.BaseCommand): - """Remove nodes from database.""" - - def get_parser(self, prog_name): - parser = super(NodeUndiscover, self).get_parser(prog_name) - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-e', - '--env', - type=int, - help='Id of environment to remove all nodes ' - 'from database.') - group.add_argument('-n', - '--node', - type=int, - help='Id of the node to remove from database.') - - parser.add_argument( - '-f', - '--force', - action='store_true', - help='Forces deletion of nodes from database ' - 'regardless of their state.') - - return parser - - def take_action(self, parsed_args): - node_ids = self.client.undiscover_nodes(env_id=parsed_args.env, - node_id=parsed_args.node, - force=parsed_args.force) - - self.app.stdout.write( - 'Nodes {0} were deleted from the database\n'.format(node_ids) - ) diff --git a/fuelclient/commands/openstack_config.py b/fuelclient/commands/openstack_config.py deleted file mode 100644 index 865b8e4d..00000000 --- a/fuelclient/commands/openstack_config.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class OpenstackConfigMixin(object): - entity_name = 'openstack-config' - - columns = ( - 'id', 'is_active', 'config_type', - 'cluster_id', 'node_id', 'node_role') - - @staticmethod - def add_env_arg(parser): - parser.add_argument( - '-e', '--env', - type=int, required=True, - help='Environment ID.') - - @staticmethod - def add_file_arg(parser): - parser.add_argument( - '--file', required=True, - type=str, help='YAML file that contains openstack configuration.') - - @staticmethod - def add_config_id_arg(parser): - parser.add_argument( - 'config', - type=int, help='Id of the OpenStack configuration.' - ) - - @staticmethod - def add_node_ids_arg(parser): - parser.add_argument( - '-n', '--node', - type=int, nargs='+', default=None, help='Ids of the nodes.' - ) - - @staticmethod - def add_node_role_arg(parser): - parser.add_argument( - '-r', '--role', - type=str, default=None, help='Role of the nodes.' - ) - - @staticmethod - def add_deleted_arg(parser): - parser.add_argument( - '-D', '--deleted', - type=bool, default=False, help='Show deleted configurations.' - ) - - @staticmethod - def add_force_arg(parser): - parser.add_argument( - '-f', '--force', - action='store_true', help='Force the update of the configuration.' - ) - - -class OpenstackConfigList(OpenstackConfigMixin, base.BaseListCommand): - """List all OpenStack configurations.""" - - def get_parser(self, prog_name): - parser = super(OpenstackConfigList, self).get_parser(prog_name) - - self.add_env_arg(parser) - self.add_node_ids_arg(parser) - self.add_node_role_arg(parser) - self.add_deleted_arg(parser) - - return parser - - def take_action(self, args): - data = self.client.get_filtered( - cluster_id=args.env, node_ids=args.node, - node_role=args.role, is_active=(not args.deleted)) - data = data_utils.get_display_data_multi(self.columns, data) - data = self._sort_data(args, data) - - return self.columns, data - - -class OpenstackConfigDownload(OpenstackConfigMixin, base.BaseCommand): - """Download specified configuration file.""" - - def get_parser(self, prog_name): - parser = super(OpenstackConfigDownload, self).get_parser(prog_name) - - self.add_config_id_arg(parser) - self.add_file_arg(parser) - - return parser - - def take_action(self, args): - file_path = self.client.download(args.config, args.file) - - msg = 'OpenStack configuration with id={c} '\ - 'downloaded to {p}.\n'.format(c=args.config, p=file_path) - - self.app.stdout.write(msg) - - -class OpenstackConfigUpload(OpenstackConfigMixin, base.BaseListCommand): - """Upload new OpenStack configuration from file.""" - - def get_parser(self, prog_name): - parser = super(OpenstackConfigUpload, self).get_parser(prog_name) - - self.add_env_arg(parser) - self.add_node_ids_arg(parser) - self.add_node_role_arg(parser) - self.add_file_arg(parser) - - return parser - - def take_action(self, args): - configs = self.client.upload(path=args.file, - cluster_id=args.env, - node_ids=args.node, - node_role=args.role) - - data = data_utils.get_display_data_multi(self.columns, configs) - return self.columns, data - - -class OpenstackConfigExecute(OpenstackConfigMixin, base.BaseCommand): - """Execute OpenStack configuration deployment.""" - - def get_parser(self, prog_name): - parser = super(OpenstackConfigExecute, self).get_parser(prog_name) - - self.add_env_arg(parser) - self.add_node_ids_arg(parser) - self.add_node_role_arg(parser) - self.add_force_arg(parser) - - return parser - - def take_action(self, args): - task = self.client.execute(cluster_id=args.env, - node_ids=args.node, - node_role=args.role, - force=args.force) - - msg = ('Deployment of the OpenStack configuration was started within ' - 'task with id {task_id}.\n').format(task_id=task['id']) - - self.app.stdout.write(msg) - - -class OpenstackConfigDelete(OpenstackConfigMixin, base.BaseCommand): - """Delete OpenStack configuration with given id.""" - - def get_parser(self, prog_name): - parser = super(OpenstackConfigDelete, self).get_parser(prog_name) - - self.add_config_id_arg(parser) - - return parser - - def take_action(self, args): - self.client.delete(args.config) - - msg = 'Openstack configuration with id {c} '\ - 'was deleted.\n'.format(c=args.config) - - self.app.stdout.write(msg) diff --git a/fuelclient/commands/plugins.py b/fuelclient/commands/plugins.py deleted file mode 100644 index ef1df34e..00000000 --- a/fuelclient/commands/plugins.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.commands import base - - -class PluginsMixIn(object): - entity_name = 'plugins' - - @staticmethod - def add_plugin_file_argument(parser): - parser.add_argument( - 'file', - type=str, - help='Path to plugin file to install' - ) - - @staticmethod - def add_plugin_name_argument(parser): - parser.add_argument( - 'name', - type=str, - help='Name of plugin to remove' - ) - - @staticmethod - def add_plugin_version_argument(parser): - parser.add_argument( - 'version', - type=str, - help='Version of plugin to remove' - ) - - @staticmethod - def add_plugin_ids_argument(parser): - parser.add_argument( - 'ids', - type=int, - nargs='*', - metavar='plugin-id', - help='Synchronise only plugins with specified ids' - ) - - @staticmethod - def add_plugin_install_force_argument(parser): - parser.add_argument( - '-f', '--force', - action='store_true', - help='Used for reinstall plugin with the same version' - ) - - -class PluginsList(PluginsMixIn, base.BaseListCommand): - """Show list of all available plugins.""" - - columns = ('id', - 'name', - 'version', - 'package_version', - 'releases') - - -class PluginsSync(PluginsMixIn, base.BaseCommand): - """Synchronise plugins on file system with plugins in API service.""" - - def get_parser(self, prog_name): - parser = super(PluginsSync, self).get_parser(prog_name) - self.add_plugin_ids_argument(parser) - return parser - - def take_action(self, parsed_args): - ids = parsed_args.ids if len(parsed_args.ids) > 0 else None - self.client.sync(ids=ids) - self.app.stdout.write("Plugins were successfully synchronized.\n") - - -class PluginInstall(PluginsMixIn, base.BaseCommand): - """Install plugin archive and register in API service.""" - - def get_parser(self, prog_name): - parser = super(PluginInstall, self).get_parser(prog_name) - self.add_plugin_file_argument(parser) - self.add_plugin_install_force_argument(parser) - return parser - - def take_action(self, parsed_args): - self.client.install(parsed_args.file, force=parsed_args.force) - self.app.stdout.write( - "Plugin {0} was successfully installed.\n".format(parsed_args.file) - ) - - -class PluginRemove(PluginsMixIn, base.BaseCommand): - """Remove the plugin package, and update data in API service.""" - - def get_parser(self, prog_name): - parser = super(PluginRemove, self).get_parser(prog_name) - self.add_plugin_name_argument(parser) - self.add_plugin_version_argument(parser) - return parser - - def take_action(self, parsed_args): - self.client.remove(parsed_args.name, parsed_args.version) - self.app.stdout.write( - "Plugin {0} was successfully removed.\n".format(parsed_args.name) - ) diff --git a/fuelclient/commands/release.py b/fuelclient/commands/release.py deleted file mode 100644 index 5edebcf3..00000000 --- a/fuelclient/commands/release.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2016 Mirantis, 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. - -from fuelclient.commands import base -from fuelclient.common import data_utils -from fuelclient import utils - - -class ReleaseMixIn(object): - entity_name = 'release' - - -class ReleaseList(ReleaseMixIn, base.BaseListCommand): - """Show list of all available releases.""" - - columns = ("id", - "name", - "state", - "operating_system", - "version") - - -class ReleaseReposList(ReleaseMixIn, base.BaseListCommand): - """Show repos for a given release.""" - - columns = ( - 'name', - 'priority', - 'uri', - 'section', - 'suite', - 'type') - - @property - def default_sorting_by(self): - return ['priority'] - - def get_parser(self, prog_name): - parser = super(ReleaseReposList, self).get_parser(prog_name) - parser.add_argument('id', type=int, - help='Id of the {0}.'.format(self.entity_name)) - return parser - - def take_action(self, parsed_args): - data = self.client.get_attributes_metadata_by_id(parsed_args.id) - repos = data["editable"]["repo_setup"]["repos"]["value"] - repos = data_utils.get_display_data_multi(self.columns, repos) - repos = self._sort_data(parsed_args, repos) - return self.columns, repos - - -class ReleaseReposUpdate(ReleaseMixIn, base.BaseCommand): - """Update repos for a given release.""" - - def get_parser(self, prog_name): - parser = super(ReleaseReposUpdate, self).get_parser(prog_name) - parser.add_argument( - '-f', '--file', action='store', required=True, - help='Input yaml file with list of repositories') - parser.add_argument( - 'id', type=int, help='Id of the {0}.'.format(self.entity_name)) - return parser - - def take_action(self, parsed_args): - data = self.client.get_attributes_metadata_by_id(parsed_args.id) - new_repos = utils.parse_yaml_file(parsed_args.file) - data["editable"]["repo_setup"]["repos"]["value"] = new_repos - self.client.update_attributes_metadata_by_id(parsed_args.id, data) - self.app.stdout.write( - "Repositories for the release with " - "id {rel_id} were set from {file}.\n".format( - rel_id=parsed_args.id, - file=parsed_args.file - ) - ) - - -class ReleaseComponentList(ReleaseMixIn, base.BaseListCommand): - """Show list of components for a given release.""" - - columns = ("name", - "requires", - "compatible", - "incompatible", - "default") - - @property - def default_sorting_by(self): - return ['name'] - - @staticmethod - def retrieve_predicates(statement): - """Retrieve predicates with respective 'items' components - - :param statement: the dictionary to extract predicate values from - :return: retrieval result as a string - """ - predicates = ('any_of', 'all_of', 'one_of', 'none_of') - for predicate in predicates: - if predicate in statement: - result = ', '.join(statement[predicate].get('items')) - return "{0} ({1})".format(predicate, result) - raise ValueError('Predicates not found.') - - @classmethod - def retrieve_data(cls, value): - """Retrieve names of components or predicates from nested data - - :param value: data to extract name or to retrieve predicates from - :return: names of components or predicates as a string - """ - if isinstance(value, list): - # get only "name" of components otherwise retrieve predicates - return ', '.join([v['name'] if 'name' in v - else cls.retrieve_predicates(v) - for v in value]) - return value - - def get_parser(self, prog_name): - parser = super(ReleaseComponentList, self).get_parser(prog_name) - parser.add_argument('id', type=int, - help='Id of the {0}.'.format(self.entity_name)) - return parser - - def take_action(self, parsed_args): - data = self.client.get_components_by_id(parsed_args.id) - # some keys (columns) can be missed in origin data - # then create them with respective '-' value - data = [{k: self.retrieve_data(d.get(k, '-')) for k in self.columns} - for d in data] - data = data_utils.get_display_data_multi(self.columns, data) - data = self._sort_data(parsed_args, data) - return self.columns, data diff --git a/fuelclient/commands/role.py b/fuelclient/commands/role.py deleted file mode 100644 index 82fe3bcb..00000000 --- a/fuelclient/commands/role.py +++ /dev/null @@ -1,268 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 abc -import os - -from oslo_utils import fileutils -import six - -from fuelclient.cli import error -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class RoleMixIn(object): - entity_name = 'role' - supported_file_formats = ('json', 'yaml') - fields_mapper = ( - ('env', 'clusters'), - ('release', 'releases') - ) - - def parse_model(self, args): - for param, role_class in self.fields_mapper: - model_id = getattr(args, param) - if model_id: - return role_class, model_id - - @staticmethod - def get_file_path(directory, owner_type, owner_id, role_name, file_format): - return os.path.join(os.path.abspath(directory), - '{owner}_{id}'.format(owner=owner_type, - id=owner_id), - '{}.{}'.format(role_name, file_format)) - - -@six.add_metaclass(abc.ABCMeta) -class BaseUploadCommand(RoleMixIn, base.BaseCommand): - """Base class for uploading metadata of a role.""" - - @abc.abstractproperty - def action(self): - """String with the name of the action.""" - pass - - @abc.abstractproperty - def uploader(self): - """Callable for uploading data.""" - pass - - def get_parser(self, prog_name): - parser = super(BaseUploadCommand, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment') - parser.add_argument('-n', - '--name', - required=True, - help='Name of role.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized role description.') - parser.add_argument('-d', - '--directory', - required=False, - default=os.path.curdir, - help='Source directory. Defaults to ' - 'the current directory.') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - params = {"owner_type": model, - "owner_id": model_id, - "role_name": parsed_args.name} - - file_path = self.get_file_path(parsed_args.directory, - model, - model_id, - parsed_args.name, - parsed_args.format) - - try: - with open(file_path, 'r') as stream: - data = data_utils.safe_load(parsed_args.format, stream) - self.uploader(data, **params) - except (OSError, IOError): - msg = "Could not read description for role '{}' at {}".format( - parsed_args.name, file_path) - raise error.InvalidFileException(msg) - - msg = ("Description of role '{role}' for {owner} with id {id} was " - "{action}d from {file_path}\n".format(role=parsed_args.name, - owner=model, - id=model_id, - action=self.action, - file_path=file_path)) - self.app.stdout.write(msg) - - -class RoleList(RoleMixIn, base.BaseListCommand): - """Show list of all available roles for release or cluster.""" - - columns = ("name", - "group", - "conflicts", - "description") - - @property - def default_sorting_by(self): - return ['name'] - - def get_parser(self, prog_name): - parser = super(RoleList, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment' - ) - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - data = self.client.get_all(model, model_id) - - data = data_utils.get_display_data_multi(self.columns, data) - data = self._sort_data(parsed_args, data) - return self.columns, data - - -class RoleDownload(RoleMixIn, base.BaseCommand): - """Download full role description to file.""" - - def get_parser(self, prog_name): - parser = super(RoleDownload, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment' - ) - parser.add_argument('-n', - '--name', - required=True, - help='Name of role.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized role description.') - parser.add_argument('-d', - '--directory', - required=False, - default=os.path.curdir, - help='Destination directory. Defaults to ' - 'the current directory.') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - file_path = self.get_file_path(parsed_args.directory, - model, - model_id, - parsed_args.name, - parsed_args.format) - data = self.client.get_one(model, - model_id, - parsed_args.name) - - try: - fileutils.ensure_tree(os.path.dirname(file_path)) - fileutils.delete_if_exists(file_path) - - with open(file_path, 'w') as stream: - data_utils.safe_dump(parsed_args.format, stream, data) - except (OSError, IOError): - msg = ("Could not store description data " - "for role {} at {}".format(parsed_args.name, file_path)) - raise error.InvalidFileException(msg) - - msg = ("Description data of role '{}' within {} id {} " - "was stored in {}\n".format(parsed_args.name, - model, - model_id, - file_path)) - self.app.stdout.write(msg) - - -class RoleUpdate(BaseUploadCommand): - """Update a role from file description.""" - - action = "update" - - @property - def uploader(self): - return self.client.update - - -class RoleCreate(BaseUploadCommand): - """Create a role from file description""" - - action = "create" - - @property - def uploader(self): - return self.client.create - - -class RoleDelete(RoleMixIn, base.BaseCommand): - """Delete a role from release or cluster""" - - def get_parser(self, prog_name): - parser = super(RoleDelete, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment' - ) - parser.add_argument('-n', - '--name', - required=True, - help='Name of role.') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - self.client.delete(model, - model_id, - parsed_args.name) - - msg = "Role '{}' was deleted from {} with id {}\n".format( - parsed_args.name, model, model_id) - self.app.stdout.write(msg) diff --git a/fuelclient/commands/sequence.py b/fuelclient/commands/sequence.py deleted file mode 100644 index 97983570..00000000 --- a/fuelclient/commands/sequence.py +++ /dev/null @@ -1,203 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient.cli import serializers -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class SequenceMixIn(object): - entity_name = 'sequence' - - -class SequenceCreate(SequenceMixIn, base.show.ShowOne, base.BaseCommand): - """Create a new deployment sequence.""" - - columns = ("id", "release_id", "name") - - def get_parser(self, prog_name): - parser = super(SequenceCreate, self).get_parser(prog_name) - - parser.add_argument( - "-r", "--release", - type=int, - required=True, - help="Release object id, sequence will be linked to." - ) - parser.add_argument( - '-n', '--name', - required=True, - help='The unique name for sequence.' - ) - parser.add_argument( - '-t', '--graph-type', - dest='graph_types', - nargs='+', - required=True, - help='Graph types, which will be included to sequence.\n' - 'Note: Order is important.' - ) - return parser - - def take_action(self, args): - new_sequence = self.client.create( - args.release, args.name, args.graph_types - ) - self.app.stdout.write("Sequence was successfully created:\n") - data = data_utils.get_display_data_single(self.columns, new_sequence) - - return self.columns, data - - -class SequenceUpload(SequenceMixIn, base.show.ShowOne, base.BaseCommand): - """Upload a new deployment sequence.""" - - columns = ("id", "release_id", "name") - - def get_parser(self, prog_name): - parser = super(SequenceUpload, self).get_parser(prog_name) - - parser.add_argument( - "-r", "--release", - type=int, - required=True, - help="Release object id, sequence will be linked to." - ) - parser.add_argument( - '--file', - required=True, - help='YAML file which contains deployment sequence properties.' - ) - return parser - - def take_action(self, args): - serializer = serializers.FileFormatBasedSerializer() - new_sequence = self.client.upload( - args.release, serializer.read_from_file(args.file) - ) - self.app.stdout.write("Sequence was successfully created:\n") - data = data_utils.get_display_data_single(self.columns, new_sequence) - return self.columns, data - - -class SequenceDownload(SequenceMixIn, base.BaseCommand): - """Download deployment sequence data.""" - - def get_parser(self, prog_name): - parser = super(SequenceDownload, self).get_parser(prog_name) - - parser.add_argument( - "id", - type=int, - help="Sequence ID." - ) - parser.add_argument( - '--file', - help='The file path where data will be saved.' - ) - return parser - - def take_action(self, args): - data = self.client.download(args.id) - if args.file: - serializer = serializers.FileFormatBasedSerializer() - serializer.write_to_file(args.file, data) - else: - serializer = serializers.Serializer("yaml") - serializer.write_to_file(self.app.stdout, data) - - -class SequenceUpdate(SequenceMixIn, base.BaseShowCommand): - """Update existing sequence.""" - - columns = ("id", "name") - - def get_parser(self, prog_name): - parser = super(SequenceUpdate, self).get_parser(prog_name) - parser.add_argument( - '-n', '--name', - required=False, - help='The unique name for sequence.' - ) - parser.add_argument( - '-t', '--graph-type', - dest='graph_types', - nargs='+', - required=False, - help='Graph types, which will be included to sequence.\n' - 'Note: Order is important.' - ) - return parser - - def take_action(self, args): - sequence = self.client.update( - args.id, name=args.name, graph_types=args.graph_types - ) - - if sequence: - self.app.stdout.write("Sequence was successfully updated:\n") - data = data_utils.get_display_data_single(self.columns, sequence) - return self.columns, data - else: - self.app.stdout.write("Nothing to update.\n") - - -class SequenceDelete(SequenceMixIn, base.BaseDeleteCommand): - """Delete existing sequence.""" - - -class SequenceShow(SequenceMixIn, base.BaseShowCommand): - """Display information about sequence.""" - columns = ("id", "release_id", "name", "graphs") - - -class SequenceList(SequenceMixIn, base.BaseListCommand): - """Show list of all existing sequences.""" - columns = ("id", "release_id", "name") - filters = {'release': 'release', 'cluster': 'env'} - - def get_parser(self, prog_name): - parser = super(SequenceList, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument( - '-r', '--release', - type=int, - help='The Release object ID.' - ) - group.add_argument( - '-e', '--env', - type=int, - help='The environment object id.' - ) - return parser - - -class SequenceExecute(SequenceMixIn, base.BaseTasksExecuteCommand): - """Executes sequence on specified environment.""" - - def get_parser(self, prog_name): - parser = super(SequenceExecute, self).get_parser(prog_name) - parser.add_argument( - 'id', - type=int, - help='Id of the Sequence.' - ) - return parser - - def get_options(self, parsed_args): - return { - 'sequence_id': parsed_args.id, - } diff --git a/fuelclient/commands/snapshot.py b/fuelclient/commands/snapshot.py deleted file mode 100644 index 7c8e1058..00000000 --- a/fuelclient/commands/snapshot.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 argparse -import os - -from oslo_utils import fileutils - -from fuelclient.cli import error -from fuelclient.commands import base -from fuelclient.common import data_utils -from fuelclient import utils - - -class SnapshotMixIn(object): - - entity_name = 'snapshot' - supported_file_formats = ('json', 'yaml') - - @staticmethod - def config_file(file_path): - if not utils.file_exists(file_path): - raise argparse.ArgumentTypeError( - 'File "{0}" does not exist'.format(file_path)) - return file_path - - @staticmethod - def get_config_path(directory, file_format): - return os.path.join(os.path.abspath(directory), - 'snapshot_conf.{}'.format(file_format)) - - -class SnapshotGenerate(SnapshotMixIn, base.BaseCommand): - """Generate diagnostic snapshot.""" - - def get_parser(self, prog_name): - parser = super(SnapshotGenerate, self).get_parser(prog_name) - parser.add_argument('-c', - '--config', - required=False, - type=self.config_file, - help='Configuration file.') - return parser - - def take_action(self, parsed_args): - file_path = parsed_args.config - - config = dict() - if file_path: - file_format = os.path.splitext(file_path)[1].lstrip('.') - try: - with open(file_path, 'r') as stream: - config = data_utils.safe_load(file_format, stream) - except (OSError, IOError): - msg = 'Could not read configuration at {}.' - raise error.InvalidFileException(msg.format(file_path)) - - result = self.client.create_snapshot(config) - - msg = "Diagnostic snapshot generation task with id {id} was started\n" - self.app.stdout.write(msg.format(id=result.id)) - - -class SnapshotConfigGetDefault(SnapshotMixIn, base.BaseCommand): - """Download default config to generate custom diagnostic snapshot.""" - - def get_parser(self, prog_name): - parser = super(SnapshotConfigGetDefault, self).get_parser(prog_name) - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized diagnostic snapshot ' - 'configuration data.') - parser.add_argument('-d', - '--directory', - required=False, - default=os.path.curdir, - help='Destination directory. Defaults to ' - 'the current directory.') - return parser - - def take_action(self, parsed_args): - file_path = self.get_config_path(parsed_args.directory, - parsed_args.format) - config = self.client.get_default_config() - - try: - fileutils.ensure_tree(os.path.dirname(file_path)) - fileutils.delete_if_exists(file_path) - - with open(file_path, 'w') as stream: - data_utils.safe_dump(parsed_args.format, stream, config) - except (OSError, IOError): - msg = 'Could not store configuration at {}.' - raise error.InvalidFileException(msg.format(file_path)) - - msg = "Configuration was stored in {path}\n" - self.app.stdout.write(msg.format(path=file_path)) - - -class SnapshotGetLink(SnapshotMixIn, base.BaseShowCommand): - """Show link to download diagnostic snapshot.""" - - columns = ('status', - 'link') - - def take_action(self, parsed_args): - data = self.client.get_by_id(parsed_args.id) - if data['name'] != 'dump': - msg = "Task with id {0} is not a snapshot generation task" - raise error.ActionException(msg.format(data['id'])) - if data['status'] != 'ready': - data['link'] = None - else: - data['link'] = self.client.connection.root + data['message'] - - data = data_utils.get_display_data_single(self.columns, data) - return self.columns, data diff --git a/fuelclient/commands/tag.py b/fuelclient/commands/tag.py deleted file mode 100644 index 8f220146..00000000 --- a/fuelclient/commands/tag.py +++ /dev/null @@ -1,265 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 abc -import os - -from oslo_utils import fileutils -import six - -from fuelclient.cli import error -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class TagMixIn(object): - entity_name = 'tag' - supported_file_formats = ('json', 'yaml') - fields_mapper = ( - ('env', 'clusters'), - ('release', 'releases') - ) - - def parse_model(self, args): - for param, tag_class in self.fields_mapper: - model_id = getattr(args, param) - if model_id: - return tag_class, model_id - - @staticmethod - def get_file_path(directory, owner_type, owner_id, tag_name, file_format): - return os.path.join(os.path.abspath(directory), - '{owner}_{id}'.format(owner=owner_type, - id=owner_id), - '{}.{}'.format(tag_name, file_format)) - - -@six.add_metaclass(abc.ABCMeta) -class BaseUploadCommand(TagMixIn, base.BaseCommand): - """Base class for uploading metadata of a tag.""" - - @abc.abstractproperty - def action(self): - """String with the name of the action.""" - pass - - @abc.abstractproperty - def uploader(self): - """Callable for uploading data.""" - pass - - def get_parser(self, prog_name): - parser = super(BaseUploadCommand, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment') - parser.add_argument('-n', - '--name', - required=True, - help='Name of tag.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized tag description.') - parser.add_argument('-d', - '--directory', - required=False, - default=os.path.curdir, - help='Source directory. Defaults to ' - 'the current directory.') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - params = {"owner_type": model, - "owner_id": model_id, - "tag_name": parsed_args.name} - - file_path = self.get_file_path(parsed_args.directory, - model, - model_id, - parsed_args.name, - parsed_args.format) - - try: - with open(file_path, 'r') as stream: - data = data_utils.safe_load(parsed_args.format, stream) - self.uploader(data, **params) - except (OSError, IOError): - msg = "Could not read description for tag '{}' at {}".format( - parsed_args.name, file_path) - raise error.InvalidFileException(msg) - - msg = ("Description of tag '{tag}' for {owner} with id {id} was " - "{action}d from {file_path}\n".format(tag=parsed_args.name, - owner=model, - id=model_id, - action=self.action, - file_path=file_path)) - self.app.stdout.write(msg) - - -class TagList(TagMixIn, base.BaseListCommand): - """Show list of all available tags for release or cluster.""" - - columns = ("name", - "group", - "conflicts", - "description") - - @property - def default_sorting_by(self): - return ['name'] - - def get_parser(self, prog_name): - parser = super(TagList, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - data = self.client.get_all(model, model_id) - - data = data_utils.get_display_data_multi(self.columns, data) - data = self._sort_data(parsed_args, data) - return self.columns, data - - -class TagDownload(TagMixIn, base.BaseCommand): - """Download full tag description to file.""" - - def get_parser(self, prog_name): - parser = super(TagDownload, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment') - parser.add_argument('-n', - '--name', - required=True, - help='Name of tag.') - parser.add_argument('-f', - '--format', - required=True, - choices=self.supported_file_formats, - help='Format of serialized tag description.') - parser.add_argument('-d', - '--directory', - required=False, - default=os.path.curdir, - help='Destination directory. Defaults to ' - 'the current directory.') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - file_path = self.get_file_path(parsed_args.directory, - model, - model_id, - parsed_args.name, - parsed_args.format) - data = self.client.get_tag(model, - model_id, - parsed_args.name) - - try: - fileutils.ensure_tree(os.path.dirname(file_path)) - fileutils.delete_if_exists(file_path) - - with open(file_path, 'w') as stream: - data_utils.safe_dump(parsed_args.format, stream, data) - except (OSError, IOError): - msg = ("Could not store description data " - "for tag {} at {}".format(parsed_args.name, file_path)) - raise error.InvalidFileException(msg) - - msg = ("Description data of tag '{}' within {} id {} " - "was stored in {}\n".format(parsed_args.name, - model, - model_id, - file_path)) - self.app.stdout.write(msg) - - -class TagUpdate(BaseUploadCommand): - """Update a tag from file description.""" - - action = "update" - - @property - def uploader(self): - return self.client.update - - -class TagCreate(BaseUploadCommand): - """Create a tag from file description""" - - action = "create" - - @property - def uploader(self): - return self.client.create - - -class TagDelete(TagMixIn, base.BaseCommand): - """Delete a tag from release or cluster""" - - def get_parser(self, prog_name): - parser = super(TagDelete, self).get_parser(prog_name) - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-r', - '--release', - type=int, - help='Id of the release') - group.add_argument('-e', - '--env', - type=int, - help='Id of the environment') - parser.add_argument('-n', - '--name', - required=True, - help='Name of tag.') - return parser - - def take_action(self, parsed_args): - model, model_id = self.parse_model(parsed_args) - self.client.delete(model, - model_id, - parsed_args.name) - - msg = "Tag '{}' was deleted from {} with id {}\n".format( - parsed_args.name, model, model_id) - self.app.stdout.write(msg) diff --git a/fuelclient/commands/task.py b/fuelclient/commands/task.py deleted file mode 100644 index 3d7a3af8..00000000 --- a/fuelclient/commands/task.py +++ /dev/null @@ -1,309 +0,0 @@ -# Copyright 2015 Mirantis, 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 - -from fuelclient.cli.serializers import Serializer -from fuelclient.commands import base -from fuelclient.common import data_utils - - -class TaskMixIn(object): - entity_name = 'task' - - @staticmethod - def add_file_arg(parser): - parser.add_argument( - '-f', - '--file', - required=False, - type=str, - help='Output file in YAML format.' - ) - - @classmethod - def write_info_to_file(cls, info_type, data, transaction_id, - serializer=None, file_path=None): - """Write additional info to the given path. - - :param info_type: deployment_info | cluster_settings | - network_configuration - :type info_type: str - :param data: data - :type data: list of dict - :param serializer: serializer - :param transaction_id: Transaction ID - :type transaction_id: str or int - :param file_path: path - :type file_path: str - :return: path to resulting file - :rtype: str - """ - serializer = serializer or Serializer() - if file_path: - return serializer.write_to_full_path( - file_path, - data - ) - else: - return serializer.write_to_path( - cls.get_default_info_path(info_type, transaction_id), - data - ) - - @staticmethod - def get_default_info_path(info_type, transaction_id): - """Generate default path for task additional info e.g. deployment info - - :param info_type: deployment_info | cluster_settings | - network_configuration - :type info_type: str - :param transaction_id: Transaction ID - :type transaction_id: str or int - :return: path - :rtype: str - """ - return os.path.join( - os.path.abspath(os.curdir), - "{info_type}_{transaction_id}".format( - info_type=info_type, - transaction_id=transaction_id) - ) - - def download_info_to_file(self, transaction_id, info_type, file_path): - """Get and save to path for task additional info e.g. deployment info - - :param transaction_id: Transaction ID - :type transaction_id: str or int - :param info_type: deployment_info | cluster_settings | - network_configuration - :type info_type: str - :param file_path: path - :type file_path: str - :return: path - :rtype: str - """ - data = self.client.download(transaction_id=transaction_id) - return self.write_info_to_file( - info_type=info_type, - data=data, - transaction_id=transaction_id, - serializer=Serializer(), - file_path=file_path) - - -class TaskInfoFileMixIn(TaskMixIn): - - def get_parser(self, prog_name): - parser = super(TaskInfoFileMixIn, self).get_parser( - prog_name) - parser.add_argument('id', type=int, help='Id of the Task.') - self.add_file_arg(parser) - return parser - - def download_info(self, parsed_args): - data_file_path = self.download_info_to_file( - transaction_id=parsed_args.id, - info_type=self.info_type, - file_path=parsed_args.file) - - return data_file_path - - -class TaskList(TaskMixIn, base.BaseListCommand): - """Show list of all available tasks.""" - columns = ('id', - 'status', - 'name', - 'graph_type', - 'cluster', - 'result', - 'dry_run', - 'progress') - filters = {'cluster_id': 'env', - 'statuses': 'statuses', - 'transaction_types': 'names'} - - def get_parser(self, prog_name): - parser = super(TaskList, self).get_parser(prog_name) - - parser.add_argument( - '-e', - '--env', - type=int, - help='Show list of tasks that belong to specified environment') - - parser.add_argument( - '-t', - '--statuses', - type=str, - choices=['pending', 'error', 'ready', 'running'], - nargs='+', - help='Show list of tasks with specified statuses') - - parser.add_argument( - '-n', - '--names', - type=str, - nargs='+', - help='Show list of tasks with specified names') - - return parser - - -class TaskShow(TaskMixIn, base.BaseShowCommand): - """Show info about task with given id.""" - columns = ('id', - 'uuid', - 'status', - 'name', - 'graph_type', - 'cluster', - 'result', - 'dry_run', - 'progress', - 'message') - - -class TaskDelete(TaskMixIn, base.BaseDeleteCommand): - """Delete task with given id.""" - - def get_parser(self, prog_name): - parser = super(TaskDelete, self).get_parser(prog_name) - - parser.add_argument('-f', - '--force', - action='store_true', - default=False, - help='Force deletion of a task without ' - 'considering its state.') - - return parser - - def take_action(self, parsed_args): - self.client.delete_by_id(parsed_args.id, parsed_args.force) - - msg = 'Task with id {ent_id} was deleted\n' - self.app.stdout.write(msg.format(ent_id=parsed_args.id)) - - -class TaskHistoryShow(TaskMixIn, base.BaseListCommand): - """Show deployment history about task with given ID.""" - - entity_name = 'deployment_history' - - columns = () - - def get_parser(self, prog_name): - parser = super(TaskHistoryShow, self).get_parser(prog_name) - - parser.add_argument('id', type=int, help='Id of the Task') - - parser.add_argument( - '-n', - '--nodes', - type=str, - nargs='+', - help='Show deployment history for specific nodes') - - parser.add_argument( - '-t', - '--statuses', - type=str, - choices=['pending', 'error', 'ready', 'running', 'skipped'], - nargs='+', - help='Show deployment history for specific statuses') - - parser.add_argument( - '-d', - '--tasks-names', - type=str, - nargs='+', - help='Show deployment history for specific deployment tasks names') - - parser.add_argument( - '-p', - '--show-parameters', - action='store_true', - default=False, - help='Show deployment tasks parameters') - parser.add_argument( - '--include-summary', - action='store_true', - default=False, - help='Show deployment tasks summary') - return parser - - def take_action(self, parsed_args): - # print parser - show_parameters = parsed_args.show_parameters - include_summary = parsed_args.include_summary - data = self.client.get_all( - transaction_id=parsed_args.id, - nodes=parsed_args.nodes, - statuses=parsed_args.statuses, - tasks_names=parsed_args.tasks_names, - include_summary=include_summary, - show_parameters=show_parameters - ) - if show_parameters: - self.columns = self.client.tasks_records_keys - else: - self.columns = self.client.history_records_keys - if include_summary: - self.columns += ('summary',) - data = data_utils.get_display_data_multi(self.columns, data) - return self.columns, data - - -class TaskNetworkConfigurationDownload(TaskInfoFileMixIn, base.BaseCommand): - """Save task network configuration to a file.""" - - entity_name = 'network-configuration' - info_type = 'network_configuration' - - def take_action(self, parsed_args): - self.app.stdout.write( - "Network configuration for task with id={0}" - " downloaded to {1}\n".format(parsed_args.id, - self.download_info(parsed_args)) - ) - - -class TaskDeploymentInfoDownload(TaskInfoFileMixIn, base.BaseCommand): - """Save task deployment info to a file.""" - - entity_name = 'deployment-info' - info_type = 'deployment_info' - - def take_action(self, parsed_args): - self.app.stdout.write( - "Deployment info for task with id={0}" - " downloaded to {1}\n".format(parsed_args.id, - self.download_info(parsed_args)) - ) - - -class TaskClusterSettingsDownload(TaskInfoFileMixIn, base.BaseCommand): - """Save task settings to a file.""" - - entity_name = 'cluster-settings' - info_type = 'cluster_settings' - - def take_action(self, parsed_args): - self.app.stdout.write( - "Cluster settings for task with id={0}" - " downloaded to {1}\n".format(parsed_args.id, - self.download_info(parsed_args)) - ) diff --git a/fuelclient/commands/vip.py b/fuelclient/commands/vip.py deleted file mode 100644 index 5f070f79..00000000 --- a/fuelclient/commands/vip.py +++ /dev/null @@ -1,182 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient.commands import base - - -class VipMixIn(object): - entity_name = 'vip' - - @staticmethod - def add_env_id_arg(parser): - parser.add_argument( - '-e', - '--env', - type=int, - required=True, - help='Environment identifier' - ) - - @staticmethod - def add_network_id_arg(parser): - parser.add_argument( - "-n", - "--network", - type=int, - default=None, - required=False, - help="Network identifier" - ) - - -class VipDownload(VipMixIn, base.BaseCommand): - """Download VIPs configuration.""" - - @staticmethod - def add_ip_address_id_arg(parser): - parser.add_argument( - "-a", - "--ip-address-id", - type=int, - default=None, - required=False, - help="IP address entity identifier" - ) - - @staticmethod - def add_network_role_arg(parser): - parser.add_argument( - "-r", - "--network-role", - type=str, - default=None, - required=False, - help="Network role string" - ) - - @staticmethod - def add_file_arg(parser): - parser.add_argument( - '-f', - '--file', - type=str, - required=False, - default=None, - help='YAML file that contains openstack configuration.' - ) - - def get_parser(self, prog_name): - parser = super(VipDownload, self).get_parser(prog_name) - self.add_env_id_arg(parser) - self.add_ip_address_id_arg(parser) - self.add_file_arg(parser) - self.add_network_id_arg(parser) - self.add_network_role_arg(parser) - return parser - - def take_action(self, args): - vips_data_file_path = self.client.download( - env_id=args.env, - ip_addr_id=args.ip_address_id, - network_id=args.network, - network_role=args.network_role, - file_path=args.file - ) - - self.app.stdout.write( - "VIP configuration for environment with id={0}" - " downloaded to {1}".format(args.env, vips_data_file_path) - ) - - -class VipUpload(VipMixIn, base.BaseCommand): - """Upload new VIPs configuration from file.""" - - @staticmethod - def add_file_arg(parser): - parser.add_argument( - '-f', - '--file', - required=True, - type=str, - help='YAML file that contains openstack configuration.' - ) - - def get_parser(self, prog_name): - parser = super(VipUpload, self).get_parser(prog_name) - self.add_env_id_arg(parser) - self.add_file_arg(parser) - return parser - - def take_action(self, args): - self.client.upload(env_id=args.env, file_path=args.file) - self.app.stdout.write("VIP configuration uploaded.") - - -class VipCreate(VipMixIn, base.BaseCommand): - """Create VIP""" - - @staticmethod - def add_vip_name_arg(parser): - parser.add_argument( - '-N', - '--name', - required=True, - type=str, - help="VIP name" - ) - - @staticmethod - def add_ip_addr_arg(parser): - parser.add_argument( - '-a', - '--address', - required=True, - type=str, - help="IP-address for the VIP" - ) - - @staticmethod - def add_vip_namespace_arg(parser): - parser.add_argument( - '--namespace', - required=False, - type=str, - help="VIP namespace" - ) - - def get_parser(self, prog_name): - parser = super(VipCreate, self).get_parser(prog_name) - self.add_env_id_arg(parser) - self.add_network_id_arg(parser) - self.add_vip_name_arg(parser) - self.add_ip_addr_arg(parser) - self.add_vip_namespace_arg(parser) - return parser - - def take_action(self, args): - vip_kwargs = { - "env_id": args.env, - "ip_addr": args.address, - "network": args.network, - "vip_name": args.name, - } - if args.namespace is not None: - vip_kwargs['vip_namespace'] = args.namespace - - self.client.create(**vip_kwargs) - - self.app.stdout.write("VIP has been created.") diff --git a/fuelclient/common/__init__.py b/fuelclient/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/common/data_utils.py b/fuelclient/common/data_utils.py deleted file mode 100644 index 7b52d683..00000000 --- a/fuelclient/common/data_utils.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2015 Mirantis, 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 json -import os -import yaml - -from fuelclient import utils - - -def get_display_data_single(fields, data, missing_field_value=None): - """Performs slicing of data by set of given fields - - :param fields: Iterable containing names of fields to be retrieved - from data - :param data: Collection of JSON objects representing some - external entities - :param missing_field_value: the value will be used for all missing fields - - :return: list containing the collection of values of the - supplied attributes. - - """ - return [data.get(field, missing_field_value) for field in fields] - - -def get_display_data_multi(fields, data): - """Performs slice of data by set of given fields for multiple objects.""" - - return [get_display_data_single(fields, elem) for elem in data] - - -def safe_load(data_format, stream): - loaders = {'json': utils.safe_deserialize(json.load), - 'yaml': utils.safe_deserialize(yaml.safe_load)} - - if data_format not in loaders: - raise ValueError('Unsupported data format.') - - loader = loaders[data_format] - return loader(stream) - - -def safe_dump(data_format, stream, data): - # The reason these dumpers are assigned to individual variables is - # making PEP8 check happy. - yaml_dumper = lambda data, stream: yaml.safe_dump(data, - stream, - default_flow_style=False) - json_dumper = lambda data, stream: json.dump(data, stream, indent=4) - dumpers = {'json': json_dumper, - 'yaml': yaml_dumper} - - if data_format not in dumpers: - raise ValueError('Unsupported data format.') - - dumper = dumpers[data_format] - dumper(data, stream) - - -def read_from_file(file_path): - data_format = os.path.splitext(file_path)[1].lstrip('.') - with open(file_path, 'r') as stream: - return safe_load(data_format, stream) - - -def write_to_file(file_path, data): - data_format = os.path.splitext(file_path)[1].lstrip('.') - with open(file_path, 'w') as stream: - safe_dump(data_format, stream, data) diff --git a/fuelclient/consts.py b/fuelclient/consts.py deleted file mode 100644 index f76aebc0..00000000 --- a/fuelclient/consts.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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. - -from collections import namedtuple - - -def Enum(*values, **kwargs): - names = kwargs.get('names') - if names: - return namedtuple('Enum', names)(*values) - return namedtuple('Enum', values)(*values) - - -SERIALIZATION_FORMAT_FLAG = 'serialization_format' - -TASK_STATUSES = Enum( - 'error', - 'pending', - 'ready', - 'running' -) diff --git a/fuelclient/fuel_client.yaml b/fuelclient/fuel_client.yaml deleted file mode 100644 index c89b3f3d..00000000 --- a/fuelclient/fuel_client.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Connection settings -SERVER_ADDRESS: "127.0.0.1" -SERVER_PORT: "8000" -OS_USERNAME: -OS_PASSWORD: -# There's a need to provide default value for -# tenant name until fuel-library is updated. -# After that, it will be removed. -OS_TENANT_NAME: "admin" -HTTP_PROXY: null -HTTP_TIMEOUT: 10 - -# Performance tests settings -PERFORMANCE_PROFILING_TESTS: 0 -PERF_TESTS_PATHS: - perf_tests_base: "/tmp/fuelclient_performance_tests/tests/" - last_performance_test: "/tmp/fuelclient_performance_tests/tests/last/" - perf_tests_results: "/tmp/fuelclient_performance_tests/results/" diff --git a/fuelclient/fuelclient_settings.py b/fuelclient/fuelclient_settings.py deleted file mode 100644 index 9a94652f..00000000 --- a/fuelclient/fuelclient_settings.py +++ /dev/null @@ -1,198 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2013-2014 Mirantis, 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 -import pkg_resources -import shutil -import sys - -import six -import yaml - -from fuelclient.cli import error - - -_SETTINGS = None - -# Format: old parameter: new parameter or None -DEPRECATION_TABLE = {'LISTEN_PORT': 'SERVER_PORT', - 'KEYSTONE_USER': 'OS_USERNAME', - 'KEYSTONE_PASS': 'OS_PASSWORD'} - -# Format: parameter: fallback parameter -FALLBACK_TABLE = {DEPRECATION_TABLE[p]: p for p in DEPRECATION_TABLE} - - -class FuelClientSettings(object): - """Represents a model of Fuel Clients settings - - Default settings are saved to $XDG_CONFIG_HOME/fuel/fuel_client.yaml on - the first run. If $XDG_CONFIG_HOME is not set, ~/.config/ directory is - used by default. - - Custom settings may be stored in any YAML-formatted file the path to - which should be supplied via the $FUELCLIENT_CUSTOM_SETTINGS environment - variable. Custom settings override default ones. - - Top level values may also be set as environment variables, e.g. - export SERVER_PORT=8080. These values have the highest priority. - - """ - def __init__(self): - settings_files = [] - - user_conf_dir = os.getenv('XDG_CONFIG_HOME', - os.path.expanduser('~/.config/')) - - # Look up for a default file distributed with the source code - default_settings = pkg_resources.resource_filename('fuelclient', - 'fuel_client.yaml') - - self.user_settings = os.path.join(user_conf_dir, 'fuel', - 'fuel_client.yaml') - custom_settings = os.getenv('FUELCLIENT_CUSTOM_SETTINGS') - - if not os.path.exists(self.user_settings) and not custom_settings: - self.populate_default_settings(default_settings, - self.user_settings) - six.print_('Settings for Fuel Client have been saved to {0}.\n' - 'Consider changing default values to the ones which ' - 'are appropriate for you.'.format(self.user_settings)) - - self._add_file_if_exists(default_settings, settings_files) - self._add_file_if_exists(self.user_settings, settings_files) - - # Add a custom settings file specified by user - self._add_file_if_exists(custom_settings, settings_files) - - self.config = {} - for sf in settings_files: - try: - self._update_from_file(sf) - except Exception as e: - msg = ('Error while reading config file ' - '%(file)s: %(err)s') % {'file': sf, 'err': str(e)} - - raise error.SettingsException(msg) - - self._update_from_env() - self._check_deprecated() - - def _add_file_if_exists(self, path_to_file, file_list): - if path_to_file and os.access(path_to_file, os.R_OK): - file_list.append(path_to_file) - - def _update_from_file(self, path): - with open(path, 'r') as custom_config: - self.config.update( - yaml.load(custom_config.read()) - ) - - def _update_from_env(self): - for k in self.config: - if k in os.environ: - self.config[k] = os.environ[k] - - def _print_deprecation_warning(self, old_option, new_option=None): - """Print deprecation warning for an option.""" - - deprecation_tpl = ('DEPRECATION WARNING: {} parameter was ' - 'deprecated and will not be supported in the next ' - 'version of python-fuelclient.') - replace_tpl = ' Please replace this parameter with {}' - - deprecation = deprecation_tpl.format(old_option) - replace = '' if new_option is None else replace_tpl.format(new_option) - - six.print_(deprecation, end='', file=sys.stderr) - six.print_(replace, file=sys.stderr) - - def _check_deprecated(self): - """Looks for deprecated options in user's configuration.""" - - dep_opts = [opt for opt in self.config if opt in DEPRECATION_TABLE] - - for opt in dep_opts: - - new_opt = DEPRECATION_TABLE.get(opt) - - # Clean up new option if it was not set by a user - # Produce a warning, if both old and new options are set. - if self.config.get(new_opt) is None: - self.config.pop(new_opt, None) - else: - six.print_('WARNING: configuration contains both {old} and ' - '{new} options set. Since {old} was deprecated, ' - 'only the value of {new} ' - 'will be used.'.format(old=opt, new=new_opt), - file=sys.stderr - ) - - self._print_deprecation_warning(opt, new_opt) - - def populate_default_settings(self, source, destination): - """Puts default configuration file to a user's home directory.""" - - try: - dst_dir = os.path.dirname(destination) - - if not os.path.exists(dst_dir): - os.makedirs(dst_dir, 0o700) - - shutil.copy(source, destination) - os.chmod(destination, 0o600) - except (IOError, OSError): - msg = ('Could not save settings to {0}. Please make sure the ' - 'directory is writable') - raise error.SettingsException(msg.format(dst_dir)) - - def update_from_command_line_options(self, options): - """Update parameters from valid command line options.""" - - for param in self.config: - opt_name = param.lower() - - value = getattr(options, opt_name, None) - if value is not None: - self.config[param] = value - - def dump(self): - return yaml.dump(self.config) - - def __getattr__(self, name): - if name in self.config: - return self.config[name] - - if name in FALLBACK_TABLE: - return self.config[FALLBACK_TABLE[name]] - - raise error.SettingsException('Value for {0} option is not ' - 'configured'.format(name)) - - def __repr__(self): - return '' - - -def _init_settings(): - global _SETTINGS - _SETTINGS = FuelClientSettings() - - -def get_settings(): - if _SETTINGS is None: - _init_settings() - - return _SETTINGS diff --git a/fuelclient/hooks.py b/fuelclient/hooks.py deleted file mode 100644 index 5b16a78f..00000000 --- a/fuelclient/hooks.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2015 Mirantis, 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. - - -def setup_hook(config): - import pbr - import pbr.packaging - - # this monkey patch is to avoid appending git version to version - pbr.packaging._get_version_from_git = lambda pre_version: pre_version diff --git a/fuelclient/main.py b/fuelclient/main.py deleted file mode 100644 index 9843552f..00000000 --- a/fuelclient/main.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2015 Mirantis, 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 logging -import sys - -from cliff import app -from cliff.commandmanager import CommandManager - -from fuelclient import fuelclient_settings -from fuelclient import utils - - -LOG = logging.getLogger(__name__) - - -class FuelClient(app.App): - """Main cliff application class. - - Performs initialization of the command manager and - configuration of basic engines. - - """ - - def build_option_parser(self, description, version, argparse_kwargs=None): - """Overrides default options for backwards compatibility.""" - - p_inst = super(FuelClient, self) - parser = p_inst.build_option_parser(description=description, - version=version, - argparse_kwargs=argparse_kwargs) - - utils.add_os_cli_parameters(parser) - - return parser - - def configure_logging(self): - super(FuelClient, self).configure_logging() - - # there is issue with management url processing by keystone client - # code in our workflow, so we have to mute appropriate keystone - # loggers in order to get rid from unprocessable errors - logging.getLogger('keystoneclient.httpclient').setLevel(logging.ERROR) - - # increase level of loggin for urllib3 to avoid of displaying - # of useless messages. List of logger names is needed for - # consistency on different execution environments that could have - # installed requests packages (which is used urllib3) of different - # versions in turn - for logger_name in ('requests.packages.urllib3.connectionpool', - 'urllib3.connectionpool'): - logging.getLogger(logger_name).setLevel(logging.WARNING) - - def run(self, argv): - options, _ = self.parser.parse_known_args(argv) - - settings = fuelclient_settings.get_settings() - settings.update_from_command_line_options(options) - - return super(FuelClient, self).run(argv) - - -def main(argv=sys.argv[1:]): - fuelclient_app = FuelClient( - description='Command line interface and Python API wrapper for Fuel.', - version='10.0.0', - command_manager=CommandManager('fuelclient', convert_underscores=True), - deferred_help=True - ) - return fuelclient_app.run(argv) diff --git a/fuelclient/objects/__init__.py b/fuelclient/objects/__init__.py deleted file mode 100644 index 157cccc9..00000000 --- a/fuelclient/objects/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -"""fuelclient.objects sub-module contains classes that mirror -functionality from nailgun objects. -""" - -from fuelclient.objects.base import BaseObject -from fuelclient.objects.environment import Environment -from fuelclient.objects.extension import Extension -from fuelclient.objects.health import Health -from fuelclient.objects.node import Node -from fuelclient.objects.node import NodeCollection -from fuelclient.objects.openstack_config import OpenstackConfig -from fuelclient.objects.release import Release -from fuelclient.objects.role import Role -from fuelclient.objects.task import DeployTask -from fuelclient.objects.task import SnapshotTask -from fuelclient.objects.task import Task -from fuelclient.objects.tag import Tag -from fuelclient.objects.fuelversion import FuelVersion -from fuelclient.objects.network_group import NetworkGroup -from fuelclient.objects.plugins import Plugins -from fuelclient.objects.sequence import Sequence diff --git a/fuelclient/objects/base.py b/fuelclient/objects/base.py deleted file mode 100644 index 30a2980e..00000000 --- a/fuelclient/objects/base.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from fuelclient.cli.serializers import Serializer -from fuelclient.client import DefaultAPIClient - - -class BaseObject(object): - """BaseObject class - base class for fuelclient.objects object classes - - 'class_api_path' - url path to object handler on Nailgun server. - 'instance_api_path' - url path template which formatted with object id - returns only one serialized object. - 'connection' - 'APIClient' class instance from fuelclient.client - """ - class_api_path = None - instance_api_path = None - connection = DefaultAPIClient - - def __init__(self, obj_id, **kwargs): - self.connection = DefaultAPIClient - self.serializer = Serializer.from_params(kwargs.get('params')) - self.id = obj_id - self._data = None - - @classmethod - def init_with_data(cls, data): - instance = cls(data["id"]) - instance._data = data - return instance - - @classmethod - def get_by_ids(cls, ids): - return map(cls, ids) - - def update(self): - self._data = self.connection.get_request( - self.instance_api_path.format(self.id)) - - def get_fresh_data(self): - self.update() - return self.data - - @property - def data(self): - if self._data is None: - return self.get_fresh_data() - else: - return self._data - - @classmethod - def get_all_data(cls, **kwargs): - return cls.connection.get_request(cls.class_api_path, params=kwargs) - - @classmethod - def get_all(cls, **kwargs): - return map(cls.init_with_data, cls.get_all_data(**kwargs)) diff --git a/fuelclient/objects/environment.py b/fuelclient/objects/environment.py deleted file mode 100644 index 79d2e651..00000000 --- a/fuelclient/objects/environment.py +++ /dev/null @@ -1,646 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from operator import attrgetter -import os -import shutil - -from fuelclient.cli import error -from fuelclient.cli.serializers import listdir_without_extensions -from fuelclient.objects.base import BaseObject -from fuelclient.objects.task import DeployTask -from fuelclient.objects.task import Task - - -class Environment(BaseObject): - - class_api_path = "clusters/" - instance_api_path = "clusters/{0}/" - deployment_tasks_path = 'clusters/{0}/deployment_tasks' - deployment_tasks_graph_path = 'clusters/{0}/deploy_tasks/graph.gv' - attributes_path = 'clusters/{0}/attributes' - network_template_path = 'clusters/{0}/network_configuration/template' - - @classmethod - def create(cls, name, release_id, net_segment_type): - data = { - "nodes": [], - "tasks": [], - "name": name, - "release_id": release_id, - "net_segment_type": net_segment_type, - } - - data = cls.connection.post_request("clusters/", data) - return cls.init_with_data(data) - - def __init__(self, *args, **kwargs): - super(Environment, self).__init__(*args, **kwargs) - self._testruns_ids = [] - - def set(self, data): - return self.connection.put_request( - "clusters/{0}/".format(self.id), - data - ) - - def delete(self): - return self.connection.delete_request( - "clusters/{0}/".format(self.id) - ) - - def assign(self, nodes, roles): - return self.connection.post_request( - "clusters/{0}/assignment/".format(self.id), - [{'id': node.id, 'roles': roles} for node in nodes] - ) - - def unassign(self, nodes): - return self.connection.post_request( - "clusters/{0}/unassignment/".format(self.id), - [{"id": n} for n in nodes] - ) - - def get_all_nodes(self): - from fuelclient.objects.node import Node - return sorted(map( - Node.init_with_data, - self.connection.get_request( - "nodes/?cluster_id={0}".format(self.id) - ) - ), key=attrgetter('id')) - - def unassign_all(self): - nodes = self.get_all_nodes() - if not nodes: - raise error.ActionException( - "Environment with id={0} doesn't have nodes to remove." - .format(self.id) - ) - return self.connection.post_request( - "clusters/{0}/unassignment/".format(self.id), - [{"id": n.id} for n in nodes] - ) - - def deploy_changes(self, dry_run=False, noop_run=False): - deploy_data = self.connection.put_request( - "clusters/{0}/changes".format(self.id), - {}, dry_run=int(dry_run), noop_run=int(noop_run) - ) - return DeployTask.init_with_data(deploy_data) - - def redeploy_changes(self, dry_run=False, noop_run=False): - deploy_data = self.connection.put_request( - "clusters/{0}/changes/redeploy".format(self.id), - {}, dry_run=int(dry_run), noop_run=int(noop_run) - ) - return DeployTask.init_with_data(deploy_data) - - def get_network_data_path(self, directory=os.curdir): - return os.path.join( - os.path.abspath(directory), - "network_{0}".format(self.id) - ) - - def get_settings_data_path(self, directory=os.curdir): - return os.path.join( - os.path.abspath(directory), - "settings_{0}".format(self.id) - ) - - def get_network_template_data_path(self, directory=None): - directory = directory or os.curdir - return os.path.join( - os.path.abspath(directory), - "network_template_{0}".format(self.id) - ) - - def write_network_data(self, network_data, directory=os.curdir, - serializer=None): - self._check_dir(directory) - return (serializer or self.serializer).write_to_path( - self.get_network_data_path(directory), - network_data - ) - - def write_settings_data(self, settings_data, directory=os.curdir, - serializer=None): - self._check_dir(directory) - return (serializer or self.serializer).write_to_path( - self.get_settings_data_path(directory), - settings_data - ) - - def write_network_template_data(self, template_data, directory=None, - serializer=None): - directory = directory or os.curdir - return (serializer or self.serializer).write_to_path( - self.get_network_template_data_path(directory), - template_data - ) - - def read_network_data(self, directory=os.curdir, - serializer=None): - self._check_dir(directory) - network_file_path = self.get_network_data_path(directory) - return (serializer or self.serializer).read_from_file( - network_file_path) - - def read_settings_data(self, directory=os.curdir, serializer=None): - self._check_dir(directory) - settings_file_path = self.get_settings_data_path(directory) - return (serializer or self.serializer).read_from_file( - settings_file_path) - - def _check_file_path(self, file_path): - if not os.path.exists(file_path): - raise error.InvalidFileException( - "File '{0}' doesn't exist.".format(file_path)) - - def _check_dir(self, directory): - if not os.path.exists(directory): - raise error.InvalidDirectoryException( - "Directory '{0}' doesn't exist.".format(directory)) - if not os.path.isdir(directory): - raise error.InvalidDirectoryException( - "Error: '{0}' is not a directory.".format(directory)) - - def read_network_template_data(self, directory=os.curdir, - serializer=None): - """Used by 'fuel' command line utility.""" - self._check_dir(directory) - network_template_file_path = self.get_network_template_data_path( - directory) - return (serializer or self.serializer).\ - read_from_file(network_template_file_path) - - def read_network_template_data_from_file(self, file_path=None, - serializer=None): - """Used by 'fuel2' command line utility.""" - return (serializer or self.serializer).\ - read_from_full_path(file_path) - - @property - def status(self): - return self.get_fresh_data()['status'] - - @property - def settings_url(self): - return self.attributes_path.format(self.id) - - @property - def default_settings_url(self): - return self.settings_url + "/defaults" - - @property - def network_url(self): - return "clusters/{id}/network_configuration/neutron".format( - **self.data - ) - - @property - def network_template_url(self): - return self.network_template_path.format(self.id) - - @property - def network_verification_url(self): - return self.network_url + "/verify" - - def get_network_data(self): - return self.connection.get_request(self.network_url) - - def get_settings_data(self): - return self.connection.get_request(self.settings_url) - - def get_default_settings_data(self): - return self.connection.get_request(self.default_settings_url) - - def get_network_template_data(self): - return self.connection.get_request(self.network_template_url) - - def set_network_data(self, data): - return self.connection.put_request( - self.network_url, data) - - def set_settings_data(self, data, force=False): - if force: - result = self.connection.put_request( - self.settings_url, data, force=1) - else: - result = self.connection.put_request( - self.settings_url, data) - return result - - def verify_network(self): - return self.connection.put_request( - self.network_verification_url, self.get_network_data()) - - def set_network_template_data(self, data): - return self.connection.put_request( - self.network_template_url, data) - - def delete_network_template_data(self): - return self.connection.delete_request(self.network_template_url) - - def _get_fact_dir_name(self, fact_type, directory=os.path.curdir): - return os.path.join( - os.path.abspath(directory), - "{0}_{1}".format(fact_type, self.id)) - - def _get_fact_url(self, fact_type, default=False): - fact_url = "clusters/{0}/orchestrator/{1}/{2}".format( - self.id, fact_type, 'defaults/' if default else '' - ) - return fact_url - - def get_default_facts(self, fact_type, **kwargs): - """Gets default facts for cluster. - :param fact_type: the type of facts (deployment, provision) - """ - return self.get_facts(fact_type, default=True, **kwargs) - - def get_facts(self, fact_type, default=False, nodes=None, split=None): - """Gets facts for cluster. - :param fact_type: the type of facts (deployment, provision) - :param default: if True, the default facts will be retrieved - :param nodes: if specified, get facts only for selected nodes - :param split: if True, the node part and common part will be split - """ - params = {} - if nodes is not None: - params['nodes'] = ','.join(str(x) for x in nodes) - if split is not None: - params['split'] = str(int(split)) - - facts = self.connection.get_request( - self._get_fact_url(fact_type, default=default), params=params - ) - if not facts: - raise error.ServerDataException( - "There is no {0} info for this " - "environment!".format(fact_type) - ) - return facts - - def upload_facts(self, fact_type, facts): - self.connection.put_request(self._get_fact_url(fact_type), facts) - - def delete_facts(self, fact_type): - self.connection.delete_request(self._get_fact_url(fact_type)) - - def read_fact_info(self, fact_type, directory, serializer=None): - return getattr( - self, "read_{0}_info".format(fact_type) - )(fact_type, directory=directory, serializer=serializer) - - def write_facts_to_dir(self, fact_type, facts, - directory=os.path.curdir, serializer=None): - dir_name = self._get_fact_dir_name(fact_type, directory=directory) - if os.path.exists(dir_name): - shutil.rmtree(dir_name) - os.makedirs(dir_name) - if isinstance(facts, dict): - engine_file_path = os.path.join(dir_name, "engine") - (serializer or self.serializer).write_to_path( - engine_file_path, facts["engine"]) - facts = facts["nodes"] - - def name_builder(fact): - return fact['name'] - else: - def name_builder(fact): - if 'role' in fact: - # from 9.0 the deployment info is serialized only per node - return "{role}_{uid}".format(**fact) - return fact['uid'] - - for _fact in facts: - fact_path = os.path.join( - dir_name, - name_builder(_fact) - ) - (serializer or self.serializer).write_to_path(fact_path, _fact) - return dir_name - - def read_deployment_info(self, fact_type, - directory=os.path.curdir, serializer=None): - self._check_dir(directory) - dir_name = self._get_fact_dir_name(fact_type, directory=directory) - self._check_dir(dir_name) - return map( - lambda f: (serializer or self.serializer).read_from_file(f), - [os.path.join(dir_name, json_file) - for json_file in listdir_without_extensions(dir_name)] - ) - - def read_provisioning_info(self, fact_type, - directory=os.path.curdir, serializer=None): - dir_name = self._get_fact_dir_name(fact_type, directory=directory) - node_facts = map( - lambda f: (serializer or self.serializer).read_from_file(f), - [os.path.join(dir_name, fact_file) - for fact_file in listdir_without_extensions(dir_name) - if "engine" != fact_file] - ) - engine = (serializer or self.serializer).read_from_file( - os.path.join(dir_name, "engine")) - return { - "engine": engine, - "nodes": node_facts - } - - # TODO(vkulanov): remove method when deprecate old cli - def get_testsets(self): - return self.connection.get_request( - 'testsets/{0}'.format(self.id), - ostf=True - ) - - @property - def is_customized(self): - data = self.get_fresh_data() - return data["is_customized"] - - # TODO(vkulanov): remove method when deprecate old cli - def is_in_running_test_sets(self, test_set): - return test_set["testset"] in self._test_sets_to_run - - # TODO(vkulanov): remove method when deprecate old cli - def run_test_sets(self, test_sets_to_run, ostf_credentials=None): - self._test_sets_to_run = test_sets_to_run - - def make_test_set(name): - result = { - "testset": name, - "metadata": { - "config": {}, - "cluster_id": self.id, - } - } - if ostf_credentials: - creds = result['metadata'].setdefault( - 'ostf_os_access_creds', {}) - if 'tenant' in ostf_credentials: - creds['ostf_os_tenant_name'] = ostf_credentials['tenant'] - if 'username' in ostf_credentials: - creds['ostf_os_username'] = ostf_credentials['username'] - if 'password' in ostf_credentials: - creds['ostf_os_password'] = ostf_credentials['password'] - return result - - tests_data = [make_test_set(ts) for ts in test_sets_to_run] - testruns = self.connection.post_request( - "testruns", tests_data, ostf=True) - self._testruns_ids = [tr['id'] for tr in testruns] - return testruns - - # TODO(vkulanov): remove method when deprecate old cli - def get_state_of_tests(self): - return [ - self.connection.get_request( - "testruns/{0}".format(testrun_id), ostf=True) - for testrun_id in self._testruns_ids - ] - - def stop(self): - return Task.init_with_data( - self.connection.put_request( - "clusters/{0}/stop_deployment/".format(self.id), - {} - ) - ) - - def reset(self, force=False): - return Task.init_with_data( - self.connection.put_request( - "clusters/{0}/reset/?force={force}".format(self.id, - force=int(force)), - {} - ) - ) - - def _get_method_url(self, method_type, nodes, force=False, noop_run=False): - endpoint = "clusters/{0}/{1}/?nodes={2}".format( - self.id, - method_type, - ','.join(map(lambda n: str(n.id), nodes))) - - if force: - endpoint += '&force=1' - if noop_run: - endpoint += '&noop_run=1' - - return endpoint - - def install_selected_nodes(self, method_type, nodes): - return Task.init_with_data( - self.connection.put_request( - self._get_method_url(method_type, nodes), - {} - ) - ) - - def execute_tasks(self, nodes, tasks, force, noop_run): - return Task.init_with_data( - self.connection.put_request( - self._get_method_url('deploy_tasks', nodes=nodes, force=force, - noop_run=noop_run), - tasks - ) - ) - - def get_tasks(self, skip=None, end=None, start=None, include=None): - """Stores logic to filter tasks by known parameters. - - :param skip: list of tasks or None - :param end: string or None - :param start: string or None - :param include: list or None - """ - tasks = [t['id'] for t in self.get_deployment_tasks( - end=end, start=start, include=include)] - if skip: - tasks_to_execute = set(tasks) - set(skip) - return list(tasks_to_execute) - return tasks - - def get_deployment_tasks(self, end=None, start=None, include=None): - url = self.deployment_tasks_path.format(self.id) - return self.connection.get_request( - url, params={ - 'end': end, - 'start': start, - 'include': include}) - - def update_deployment_tasks(self, data): - url = self.deployment_tasks_path.format(self.id) - return self.connection.put_request(url, data) - - def get_attributes(self): - return self.connection.get_request(self.settings_url) - - def update_attributes(self, data, force=False): - if force: - result = self.connection.put_request( - self.settings_url, data, force=1) - else: - result = self.connection.put_request( - self.settings_url, data) - return result - - def get_deployment_tasks_graph(self, tasks, parents_for=None, remove=None): - url = self.deployment_tasks_graph_path.format(self.id) - params = { - 'tasks': ','.join(tasks), - 'parents_for': parents_for, - 'remove': ','.join(remove) if remove else None, - } - resp = self.connection.get_request_raw(url, params=params) - resp.raise_for_status() - return resp.text - - def spawn_vms(self): - url = 'clusters/{0}/spawn_vms/'.format(self.id) - return self.connection.put_request(url, {}) - - def _get_ip_addrs_url(self, vips=True, ip_addr_id=None): - """Generate ip address management url. - - :param vips: manage vip properties of ip address - :type vips: bool - :param ip_addr_id: ip address identifier - :type ip_addr_id: int - :return: url - :rtype: str - """ - ip_addr_url = "clusters/{0}/network_configuration/ips/".format(self.id) - if ip_addr_id: - ip_addr_url += '{0}/'.format(ip_addr_id) - if vips: - ip_addr_url += 'vips/' - - return ip_addr_url - - def get_default_vips_data_path(self): - """Get path where VIPs data is located. - :return: path - :rtype: str - """ - return os.path.join( - os.path.abspath(os.curdir), - "vips_{0}".format(self.id) - ) - - def get_vips_data(self, ip_address_id=None, network=None, - network_role=None): - """Get one or multiple vip data records. - - :param ip_address_id: ip addr id could be specified to download single - vip if no ip_addr_id specified multiple entities is - returned respecting network and network_role - filters - :type ip_address_id: int - :param network: network id could be specified to filter vips - :type network: int - :param network_role: network role could be specified to filter vips - :type network_role: string - :return: response JSON - :rtype: list of dict - """ - params = {} - if network: - params['network'] = network - if network_role: - params['network-role'] = network_role - - result = self.connection.get_request( - self._get_ip_addrs_url(True, ip_addr_id=ip_address_id), - params=params - ) - if ip_address_id is not None: # single vip is returned - # wrapping with list is required to respect case when administrator - # is downloading vip address info to change it and upload - # back. Uploading works only with lists of records. - result = [result] - return result - - def write_vips_data_to_file(self, vips_data, serializer=None, - file_path=None): - """Write VIP data to the given path. - - :param vips_data: vip data - :type vips_data: list of dict - :param serializer: serializer - :param file_path: path - :type file_path: str - :return: path to resulting file - :rtype: str - """ - serializer = serializer or self.serializer - - if file_path: - return serializer.write_to_full_path( - file_path, - vips_data - ) - else: - return serializer.write_to_path( - self.get_default_vips_data_path(), - vips_data - ) - - def read_vips_data_from_file(self, file_path=None, serializer=None): - """Read VIPs data from given path. - - :param file_path: path - :type file_path: str - :param serializer: serializer object - :type serializer: object - :return: data - :rtype: list|object - """ - self._check_file_path(file_path) - return (serializer or self.serializer).read_from_file(file_path) - - def set_vips_data(self, data): - """Sending VIPs data to the Nailgun API. - - :param data: VIPs data - :type data: list of dict - :return: request result - :rtype: object - """ - return self.connection.put_request(self._get_ip_addrs_url(), data) - - def create_vip(self, **vip_kwargs): - """Create VIP through request to Nailgun API - - :param vip_data: attributes of the VIP to be created - """ - return self.connection.post_request(self._get_ip_addrs_url(), - vip_kwargs) - - def get_enabled_plugins(self): - """Get list of enabled plugins ids. - - :returns: plugins ids list - :rtype: list[int] - """ - attrs = self.get_attributes()['editable'] - enabled_plugins_ids = [] - for attr_name in attrs: - metadata = attrs[attr_name].get('metadata', {}) - if metadata.get('class') == 'plugin' and metadata.get('enabled'): - enabled_plugins_ids.append(metadata['chosen_id']) - return enabled_plugins_ids diff --git a/fuelclient/objects/extension.py b/fuelclient/objects/extension.py deleted file mode 100644 index 696253db..00000000 --- a/fuelclient/objects/extension.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -from fuelclient.objects.base import BaseObject - - -class Extension(BaseObject): - - class_api_path = "extensions/" - instance_api_path = "clusters/{0}/extensions/" - - @property - def extensions_url(self): - return self.instance_api_path.format(self.id) - - def get_env_extensions(self): - """Get list of extensions through request to the Nailgun API - - """ - return self.connection.get_request(self.extensions_url) - - def enable_env_extensions(self, extensions): - """Enable extensions through request to the Nailgun API - - :param extensions: list of extenstion to be enabled - """ - return self.connection.put_request(self.extensions_url, extensions) - - def disable_env_extensions(self, extensions): - """Disable extensions through request to the Nailgun API - - :param extensions: list of extenstion to be disabled - """ - url = '{0}?extension_names={1}'.format(self.extensions_url, - ','.join(extensions)) - return self.connection.delete_request(url) diff --git a/fuelclient/objects/fuelversion.py b/fuelclient/objects/fuelversion.py deleted file mode 100644 index b65c11e4..00000000 --- a/fuelclient/objects/fuelversion.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.objects.base import BaseObject - - -class FuelVersion(BaseObject): - - class_api_path = "version/" - - @classmethod - def get_feature_groups(cls): - return cls.get_all_data()['feature_groups'] diff --git a/fuelclient/objects/health.py b/fuelclient/objects/health.py deleted file mode 100644 index 1592cbd2..00000000 --- a/fuelclient/objects/health.py +++ /dev/null @@ -1,86 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 fuelclient.objects.base import BaseObject - - -class Health(BaseObject): - - class_api_path = "testruns/" - instance_api_path = "testruns/{0}/" - test_sets_api_path = "testsets/{0}/" - - @classmethod - def get_test_sets(cls, environment_id): - return cls.connection.get_request( - cls.test_sets_api_path.format(environment_id), - ostf=True - ) - - @classmethod - def get_tests_status_all(cls): - return cls.connection.get_request(cls.class_api_path, ostf=True) - - def get_tests_status_single(self): - return self.connection.get_request( - self.instance_api_path.format(self.id), - ostf=True - ) - - @classmethod - def get_last_tests_status(cls, environment_id): - return cls.connection.get_request( - 'testruns/last/{0}'.format(environment_id), - ostf=True - ) - - @classmethod - def run_test_sets(cls, environment_id, test_sets_to_run, - ostf_credentials=None): - - def make_test_set(name): - result = { - "testset": name, - "metadata": { - "config": {}, - "cluster_id": environment_id, - } - } - if ostf_credentials: - creds = result['metadata'].setdefault( - 'ostf_os_access_creds', {}) - if 'tenant' in ostf_credentials: - creds['ostf_os_tenant_name'] = ostf_credentials['tenant'] - if 'username' in ostf_credentials: - creds['ostf_os_username'] = ostf_credentials['username'] - if 'password' in ostf_credentials: - creds['ostf_os_password'] = ostf_credentials['password'] - return result - - tests_data = [make_test_set(ts) for ts in test_sets_to_run] - test_runs = cls.connection.post_request(cls.class_api_path, - tests_data, - ostf=True) - return test_runs - - def action_test(self, action_status): - data = [{ - "id": self.id, - "status": action_status - }] - return self.connection.put_request( - 'testruns/', data, ostf=True - ) diff --git a/fuelclient/objects/network_group.py b/fuelclient/objects/network_group.py deleted file mode 100644 index 3547c7ed..00000000 --- a/fuelclient/objects/network_group.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from operator import attrgetter - -from fuelclient.objects.base import BaseObject - - -class NetworkGroup(BaseObject): - - class_api_path = "networks/" - instance_api_path = "networks/{0}/" - - @property - def name(self): - return self.get_fresh_data()["name"] - - @classmethod - def create(cls, name, release, vlan, cidr, gateway, - group_id, meta=None): - - metadata = { - 'notation': 'cidr', - 'render_type': None, - 'map_priority': 2, - 'configurable': True, - 'use_gateway': False, - 'name': name, - 'cidr': cidr, - 'vlan_start': vlan - } - if meta: - metadata.update(meta) - - network_group = { - 'name': name, - 'release': release, - 'vlan_start': vlan, - 'cidr': cidr, - 'gateway': gateway, - 'meta': metadata, - 'group_id': group_id, - } - - data = cls.connection.post_request( - cls.class_api_path, - network_group, - ) - return cls.init_with_data(data) - - def set(self, data): - vlan = data.pop('vlan', None) - if vlan is not None: - data['vlan_start'] = vlan - - return self.connection.put_request( - self.instance_api_path.format(self.id), data) - - def delete(self): - return self.connection.delete_request( - self.instance_api_path.format(self.id) - ) - - -class NetworkGroupCollection(object): - - def __init__(self, networks): - self.collection = networks - - @classmethod - def init_with_ids(cls, ids): - return cls(map(NetworkGroup, ids)) - - @classmethod - def init_with_data(cls, data): - return cls(map(NetworkGroup.init_with_data, data)) - - def __str__(self): - return "{0} [{1}]".format( - self.__class__.__name__, - ", ".join(map(lambda n: str(n.id), self.collection)) - ) - - def __iter__(self): - return iter(self.collection) - - @property - def data(self): - return map(attrgetter("data"), self.collection) - - @classmethod - def get_all(cls): - return cls(NetworkGroup.get_all()) - - def filter_by_group_id(self, group_id): - self.collection = filter(lambda net: net.data['group_id'] == group_id, - self.collection) diff --git a/fuelclient/objects/node.py b/fuelclient/objects/node.py deleted file mode 100644 index f9d240d8..00000000 --- a/fuelclient/objects/node.py +++ /dev/null @@ -1,206 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from operator import attrgetter -import os - -from fuelclient.cli.error import InvalidDirectoryException -from fuelclient.objects.base import BaseObject -from fuelclient.objects.environment import Environment - - -class Node(BaseObject): - - class_api_path = "nodes/" - instance_api_path = "nodes/{0}/" - attributes_api_path = "nodes/{0}/attributes/" - - attributes_urls = { - "interfaces": ("interfaces", "default_assignment"), - "disks": ("disks", "defaults") - } - - @property - def env_id(self): - return self.get_fresh_data()["cluster"] - - @property - def env(self): - return Environment(self.env_id) - - def get_attributes_path(self, directory): - return os.path.join( - os.path.abspath( - os.curdir if directory is None else directory), - "node_{0}".format(self.id) - ) - - def is_finished(self, latest=True): - if latest: - data = self.get_fresh_data() - else: - data = self.data - return data["status"] in ("ready", "error") - - @property - def progress(self): - data = self.get_fresh_data() - return data["progress"] - - @property - def labels(self): - return self.get_fresh_data().get('labels', {}) - - def get_attribute_default_url(self, attributes_type): - url_path, default_url_path = self.attributes_urls[attributes_type] - return "nodes/{0}/{1}/{2}".format(self.id, url_path, default_url_path) - - def get_attribute_url(self, attributes_type): - url_path, _ = self.attributes_urls[attributes_type] - return "nodes/{0}/{1}/".format(self.id, url_path) - - def get_default_attribute(self, attributes_type): - return self.connection.get_request( - self.get_attribute_default_url(attributes_type) - ) - - def get_node_attributes(self): - return self.connection.get_request( - self.attributes_api_path.format(self.id) - ) - - def update_node_attributes(self, data): - return self.connection.put_request( - self.attributes_api_path.format(self.id), - data - ) - - def get_attribute(self, attributes_type): - return self.connection.get_request( - self.get_attribute_url(attributes_type) - ) - - def upload_node_attribute(self, attributes_type, attributes): - url = self.get_attribute_url(attributes_type) - return self.connection.put_request( - url, - attributes - ) - - def write_attribute(self, attribute_type, attributes, - directory, serializer=None): - attributes_directory = self.get_attributes_path(directory) - if not os.path.exists(attributes_directory): - os.mkdir(attributes_directory) - attribute_path = os.path.join( - attributes_directory, - attribute_type - ) - if os.path.exists(attribute_path): - os.remove(attribute_path) - return (serializer or self.serializer).write_to_path( - attribute_path, - attributes - ) - - def read_attribute(self, attributes_type, directory, serializer=None): - attributes_directory = self.get_attributes_path(directory) - if not os.path.exists(attributes_directory): - raise InvalidDirectoryException( - "Folder {0} doesn't contain node folder '{1}'" - .format(directory, "node_{0}".format(self.id)) - ) - return (serializer or self.serializer).read_from_file( - os.path.join( - attributes_directory, - attributes_type - ) - ) - - def deploy(self): - self.env.install_selected_nodes("deploy", (self,)) - - def provision(self): - self.env.install_selected_nodes("provision", (self,)) - - def delete(self): - self.connection.delete_request(self.instance_api_path.format(self.id)) - - def node_vms_create(self, config): - url = "nodes/{0}/vms_conf/".format(self.id) - return self.connection.put_request(url, {'vms_conf': config}) - - def get_node_vms_conf(self): - url = "nodes/{0}/vms_conf/".format(self.id) - return self.connection.get_request(url) - - def set(self, data): - return self.connection.put_request( - self.instance_api_path.format(self.id), - data - ) - - @classmethod - def get_by_env_id(cls, cluster_id): - params = {'cluster_id': cluster_id} - return cls.connection.get_request(cls.class_api_path, params=params) - - -class NodeCollection(object): - - class_api_path = "nodes/" - - def __init__(self, nodes): - self.collection = nodes - - @classmethod - def init_with_ids(cls, ids): - return cls(list(map(Node, ids))) - - @classmethod - def init_with_data(cls, data): - return cls(list(map(Node.init_with_data, data))) - - def __str__(self): - return "nodes [{0}]".format( - ", ".join(map(lambda n: str(n.id), self.collection)) - ) - - def __iter__(self): - return iter(self.collection) - - @property - def data(self): - return map(attrgetter("data"), self.collection) - - @classmethod - def get_all(cls): - return cls(Node.get_all()) - - @classmethod - def update(cls, data): - return BaseObject.connection.put_request(cls.class_api_path, data) - - @classmethod - def delete_by_ids(cls, ids): - url = '{0}?ids={1}'.format( - cls.class_api_path, - ','.join(map(str, ids)) - ) - - return BaseObject.connection.delete_request(url) - - def filter_by_env_id(self, env_id): - predicate = lambda node: node.data['cluster'] == env_id - self.collection = filter(predicate, self.collection) diff --git a/fuelclient/objects/nodegroup.py b/fuelclient/objects/nodegroup.py deleted file mode 100644 index 0c82c063..00000000 --- a/fuelclient/objects/nodegroup.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from operator import attrgetter - -from fuelclient.objects.base import BaseObject -from fuelclient.objects import NodeCollection - - -class NodeGroup(BaseObject): - - class_api_path = "nodegroups/" - instance_api_path = "nodegroups/{0}/" - - @property - def env_id(self): - return self.get_fresh_data()["cluster_id"] - - @property - def name(self): - return self.get_fresh_data()["name"] - - @classmethod - def create(cls, name, cluster_id): - return cls.connection.post_request( - cls.class_api_path, - {'cluster_id': cluster_id, 'name': name}, - ) - - @classmethod - def delete(cls, group_id): - return cls.connection.delete_request( - cls.instance_api_path.format(group_id) - ) - - def assign(self, nodes): - data = [{"id": n, "group_id": int(self.id)} for n in nodes] - NodeCollection.update(data) - - -class NodeGroupCollection(object): - - def __init__(self, groups): - self.collection = groups - - @classmethod - def init_with_ids(cls, ids): - return cls(map(NodeGroup, ids)) - - @classmethod - def init_with_data(cls, data): - return cls(map(NodeGroup.init_with_data, data)) - - def __str__(self): - return "node groups [{0}]".format( - ", ".join(map(lambda n: str(n.id), self.collection)) - ) - - def __iter__(self): - return iter(self.collection) - - @property - def data(self): - return map(attrgetter("data"), self.collection) - - @classmethod - def get_all(cls): - return cls(NodeGroup.get_all()) - - def filter_by_env_id(self, env_id): - predicate = lambda group: group.data['cluster_id'] == env_id - self.collection = filter(predicate, self.collection) diff --git a/fuelclient/objects/notifications.py b/fuelclient/objects/notifications.py deleted file mode 100644 index 668e2289..00000000 --- a/fuelclient/objects/notifications.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.cli import error - -from fuelclient.objects import base - - -class Notifications(base.BaseObject): - - class_api_path = "notifications/" - instance_api_path = "notifications/{0}" - - default_topic = 'done' - - @classmethod - def mark_as_read(cls, ids=None): - if not ids: - raise error.BadDataException('Message id not specified.') - - if '*' in ids: - data = Notifications.get_all_data() - else: - try: - ids = map(int, ids) - except ValueError: - raise error.BadDataException( - "Numerical ids expected or the '*' symbol.") - notifications = Notifications.get_by_ids(ids) - - data = [notification.get_fresh_data() - for notification in notifications] - - for notification in data: - notification['status'] = 'read' - - resp = cls.connection.put_request( - cls.class_api_path, data) - - return resp - - @classmethod - def send(cls, message, topic=default_topic): - if not topic: - topic = cls.default_topic - - if not message: - raise error.BadDataException('Message not specified.') - - resp = cls.connection.post_request( - cls.class_api_path, { - 'message': message, - 'topic': topic, - }) - - return resp diff --git a/fuelclient/objects/openstack_config.py b/fuelclient/objects/openstack_config.py deleted file mode 100644 index 299b0402..00000000 --- a/fuelclient/objects/openstack_config.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2015 Mirantis, 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 - -import six - -from fuelclient.cli import error -from fuelclient.cli.serializers import Serializer -from fuelclient.objects.base import BaseObject - - -class OpenstackConfig(BaseObject): - - class_api_path = 'openstack-config/' - instance_api_path = 'openstack-config/{0}/' - execute_api_path = 'openstack-config/execute/' - - @classmethod - def _prepare_params(cls, filters): - return dict((k, v) for k, v in six.iteritems(filters) if v is not None) - - @classmethod - def create(cls, **kwargs): - params = cls._prepare_params(kwargs) - data = cls.connection.post_request(cls.class_api_path, params) - return [cls.init_with_data(item) for item in data] - - def delete(self): - return self.connection.delete_request( - self.instance_api_path.format(self.id)) - - @classmethod - def execute(cls, **kwargs): - params = cls._prepare_params(kwargs) - return cls.connection.put_request(cls.execute_api_path, params) - - @classmethod - def get_filtered_data(cls, **kwargs): - url = cls.class_api_path - params = cls._prepare_params(kwargs) - - node_ids = params.get('node_ids') - if node_ids is not None: - params['node_ids'] = ','.join([str(n) for n in node_ids]) - - return cls.connection.get_request(url, params=params) - - @classmethod - def read_file(cls, path): - if not os.path.exists(path): - raise error.InvalidFileException( - "File '{0}' doesn't exist.".format(path)) - - serializer = Serializer() - return serializer.read_from_full_path(path) - - @classmethod - def write_file(cls, path, data): - serializer = Serializer() - return serializer.write_to_full_path(path, data) diff --git a/fuelclient/objects/plugins.py b/fuelclient/objects/plugins.py deleted file mode 100644 index b9bea5ea..00000000 --- a/fuelclient/objects/plugins.py +++ /dev/null @@ -1,526 +0,0 @@ -# Copyright 2014 Mirantis, 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 abc -import json -import os -import shutil -import subprocess -import sys -import tarfile - -from distutils.version import StrictVersion - -import six -import yaml - -from fuelclient.cli import error -from fuelclient.objects import base -from fuelclient import utils - -IS_MASTER = None -FUEL_PACKAGE = 'fuel' -PLUGINS_PATH = '/var/www/nailgun/plugins/' -METADATA_MASK = '/var/www/nailgun/plugins/*/metadata.yaml' - - -def raise_error_if_not_master(): - """Raises error if it's not Fuel master - - :raises: error.WrongEnvironmentError - """ - msg_tail = 'Action can be performed from Fuel master node only.' - global IS_MASTER - if IS_MASTER is None: - IS_MASTER = False - rpm_exec = utils.find_exec('rpm') - if not rpm_exec: - msg = 'Command "rpm" not found. ' + msg_tail - raise error.WrongEnvironmentError(msg) - command = [rpm_exec, '-q', FUEL_PACKAGE] - p = subprocess.Popen( - command, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - p.communicate() - if p.poll() == 0: - IS_MASTER = True - if not IS_MASTER: - msg = 'Package "fuel" is not installed. ' + msg_tail - raise error.WrongEnvironmentError(msg) - - -def master_only(f): - """Decorator for the method, which raises error, if method - is called on the node which is not Fuel master - """ - @six.wraps(f) - def print_message(*args, **kwargs): - raise_error_if_not_master() - return f(*args, **kwargs) - - return print_message - - -@six.add_metaclass(abc.ABCMeta) -class BasePlugin(object): - - @abc.abstractmethod - def install(cls, plugin_path, force=False): - """Installs plugin package - """ - - @abc.abstractmethod - def update(cls, plugin_path): - """Updates the plugin - """ - - @abc.abstractmethod - def remove(cls, plugin_name, plugin_version): - """Removes the plugin from file system - """ - - @abc.abstractmethod - def downgrade(cls, plugin_path): - """Downgrades the plugin - """ - - @abc.abstractmethod - def name_from_file(cls, file_path): - """Retrieves name from plugin package - """ - - @abc.abstractmethod - def version_from_file(cls, file_path): - """Retrieves version from plugin package - """ - - -class PluginV1(BasePlugin): - - metadata_config = 'metadata.yaml' - - def deprecated(f): - """Prints deprecation warning for old plugins - """ - @six.wraps(f) - def print_message(*args, **kwargs): - six.print_( - 'DEPRECATION WARNING: The plugin has old 1.0 package format, ' - 'this format does not support many features, such as ' - 'plugins updates, find plugin in new format or migrate ' - 'and rebuild this one.', file=sys.stderr) - return f(*args, **kwargs) - - return print_message - - @classmethod - @master_only - @deprecated - def install(cls, plugin_path, force=False): - plugin_tar = tarfile.open(plugin_path, 'r') - try: - plugin_tar.extractall(PLUGINS_PATH) - finally: - plugin_tar.close() - - @classmethod - @master_only - @deprecated - def remove(cls, plugin_name, plugin_version): - plugin_path = os.path.join( - PLUGINS_PATH, '{0}-{1}'.format(plugin_name, plugin_version)) - shutil.rmtree(plugin_path) - - @classmethod - def update(cls, _): - raise error.BadDataException( - 'Update action is not supported for old plugins with ' - 'package version "1.0.0", you can install your plugin ' - 'or use newer plugin format.') - - @classmethod - def downgrade(cls, _): - raise error.BadDataException( - 'Downgrade action is not supported for old plugins with ' - 'package version "1.0.0", you can install your plugin ' - 'or use newer plugin format.') - - @classmethod - def name_from_file(cls, file_path): - """Retrieves plugin name from plugin archive. - - :param str plugin_path: path to the plugin - :returns: plugin name - """ - return cls._get_metadata(file_path)['name'] - - @classmethod - def version_from_file(cls, file_path): - """Retrieves plugin version from plugin archive. - - :param str plugin_path: path to the plugin - :returns: plugin version - """ - return cls._get_metadata(file_path)['version'] - - @classmethod - def _get_metadata(cls, plugin_path): - """Retrieves metadata from plugin archive - - :param str plugin_path: path to the plugin - :returns: metadata from the plugin - """ - plugin_tar = tarfile.open(plugin_path, 'r') - - try: - for member_name in plugin_tar.getnames(): - if cls.metadata_config in member_name: - return yaml.load( - plugin_tar.extractfile(member_name).read()) - finally: - plugin_tar.close() - - -class PluginV2(BasePlugin): - - @classmethod - @master_only - def install(cls, plugin_path, force=False): - if force: - utils.exec_cmd( - 'yum -y install --disablerepo=\'*\' {0} || ' - 'yum -y reinstall --disablerepo=\'*\' {0}' - .format(plugin_path)) - else: - utils.exec_cmd('yum -y install --disablerepo=\'*\' {0}' - .format(plugin_path)) - - @classmethod - @master_only - def remove(cls, name, version): - rpm_name = '{0}-{1}'.format(name, utils.major_plugin_version(version)) - utils.exec_cmd('yum -y remove {0}'.format(rpm_name)) - - @classmethod - @master_only - def update(cls, plugin_path): - utils.exec_cmd('yum -y update {0}'.format(plugin_path)) - - @classmethod - @master_only - def downgrade(cls, plugin_path): - utils.exec_cmd('yum -y downgrade {0}'.format(plugin_path)) - - @classmethod - def name_from_file(cls, file_path): - """Retrieves plugin name from RPM. RPM name contains - the version of the plugin, which should be removed. - - :param str file_path: path to rpm file - :returns: name of the plugin - """ - for line in utils.exec_cmd_iterator( - "rpm -qp --queryformat '%{{name}}' {0}".format(file_path)): - name = line - break - - return cls._remove_major_plugin_version(name) - - @classmethod - def version_from_file(cls, file_path): - """Retrieves plugin version from RPM. - - :param str file_path: path to rpm file - :returns: version of the plugin - """ - for line in utils.exec_cmd_iterator( - "rpm -qp --queryformat '%{{version}}' {0}".format(file_path)): - version = line - break - - return version - - @classmethod - def _remove_major_plugin_version(cls, name): - """Removes the version from plugin name. - Here is an example: "name-1.0" -> "name" - - :param str name: plugin name - :returns: the name withot version - """ - name_wo_version = name - - if '-' in name_wo_version: - name_wo_version = '-'.join(name.split('-')[:-1]) - - return name_wo_version - - -class Plugins(base.BaseObject): - - class_api_path = 'plugins/' - class_instance_path = 'plugins/{id}' - - @classmethod - def register(cls, name, version, force=False): - """Tries to find plugin on file system, creates - it in API service if it exists. - - :param str name: plugin name - :param str version: plugin version - :param bool force: if True updates meta information - about the plugin even it does not - support updates - """ - metadata = None - for m in utils.glob_and_parse_yaml(METADATA_MASK): - if m.get('version') == version and \ - m.get('name') == name: - metadata = m - break - - if not metadata: - raise error.BadDataException( - 'Plugin {0} with version {1} does ' - 'not exist, install it and try again'.format( - name, version)) - - return cls.update_or_create(metadata, force=force) - - @classmethod - def sync(cls, plugin_ids=None): - """Checks all of the plugins on file systems, - and makes sure that they have consistent information - in API service. - - :params plugin_ids: list of ids for plugins which should be synced - :type plugin_ids: list - :returns: None - """ - post_data = None - if plugin_ids is not None: - post_data = {'ids': plugin_ids} - - cls.connection.post_request( - api='plugins/sync/', data=post_data) - - @classmethod - def unregister(cls, name, version): - """Removes the plugin from API service - - :param str name: plugin name - :param str version: plugin version - """ - plugin = cls.get_plugin(name, version) - return cls.connection.delete_request( - cls.class_instance_path.format(**plugin)) - - @classmethod - def install(cls, plugin_path, force=False): - """Installs the package, and creates data in API service - - :param str plugin_path: Name of plugin file - :param bool force: Updates existent plugin even if it is not updatable - :return: Plugins information - :rtype: dict - """ - if not utils.file_exists(plugin_path): - raise error.BadDataException( - "No such plugin file: {0}".format(plugin_path) - ) - plugin = cls.make_obj_by_file(plugin_path) - - name = plugin.name_from_file(plugin_path) - version = plugin.version_from_file(plugin_path) - - plugin.install(plugin_path, force=force) - response = cls.register(name, version, force=force) - - return response - - @classmethod - def remove(cls, plugin_name, plugin_version): - """Removes the package, and updates data in API service - - :param str name: plugin name - :param str version: plugin version - """ - plugin = cls.make_obj_by_name(plugin_name, plugin_version) - cls.unregister(plugin_name, plugin_version) - return plugin.remove(plugin_name, plugin_version) - - @classmethod - def update(cls, plugin_path): - """Updates the package, and updates data in API service - - :param str plugin_path: path to the plugin - """ - plugin = cls.make_obj_by_file(plugin_path) - - name = plugin.name_from_file(plugin_path) - version = plugin.version_from_file(plugin_path) - - plugin.update(plugin_path) - return cls.register(name, version) - - @classmethod - def downgrade(cls, plugin_path): - """Downgrades the package, and updates data in API service - - :param str plugin_path: path to the plugin - """ - plugin = cls.make_obj_by_file(plugin_path) - - name = plugin.name_from_file(plugin_path) - version = plugin.version_from_file(plugin_path) - - plugin.downgrade(plugin_path) - return cls.register(name, version) - - @classmethod - def make_obj_by_name(cls, name, version): - """Finds appropriate plugin class version, - by plugin version and name. - - :param str name: - :param str version: - :returns: plugin class - :raises: error.BadDataException unsupported package version - """ - plugin = cls.get_plugin(name, version) - package_version = plugin['package_version'] - - if StrictVersion('1.0.0') <= \ - StrictVersion(package_version) < \ - StrictVersion('2.0.0'): - return PluginV1 - elif StrictVersion('2.0.0') <= StrictVersion(package_version): - return PluginV2 - - raise error.BadDataException( - 'Plugin {0}=={1} has unsupported package version {2}'.format( - name, version, package_version)) - - @classmethod - def make_obj_by_file(cls, file_path): - """Finds appropriate plugin class version, - by plugin file. - - :param str file_path: plugin path - :returns: plugin class - :raises: error.BadDataException unsupported package version - """ - _, ext = os.path.splitext(file_path) - - if ext == '.fp': - return PluginV1 - elif ext == '.rpm': - return PluginV2 - - raise error.BadDataException( - 'Plugin {0} has unsupported format {1}'.format( - file_path, ext)) - - @classmethod - def update_or_create(cls, metadata, force=False): - """Try to update existent plugin or create new one. - - :param dict metadata: plugin information - :param bool force: updates existent plugin even if - it is not updatable - """ - # Try to update plugin - plugin_for_update = cls.get_plugin_for_update(metadata) - if plugin_for_update: - url = cls.class_instance_path.format(id=plugin_for_update['id']) - resp = cls.connection.put_request(url, metadata) - return resp - - # If plugin is not updatable it means that we should - # create new instance in Nailgun - resp_raw = cls.connection.post_request_raw( - cls.class_api_path, metadata) - resp = resp_raw.json() - - if resp_raw.status_code == 409 and force: - # Replace plugin information - message = json.loads(resp['message']) - url = cls.class_instance_path.format(id=message['id']) - resp = cls.connection.put_request(url, metadata) - elif resp_raw.status_code == 409: - error.exit_with_error( - "Nothing to do: %(title)s, version " - "%(package_version)s, does not update " - "installed plugin." % metadata) - else: - resp_raw.raise_for_status() - - return resp - - @classmethod - def get_plugin_for_update(cls, metadata): - """Retrieves plugins which can be updated - - :param dict metadata: plugin metadata - :returns: dict with plugin which can be updated or None - """ - if not cls.is_updatable(metadata['package_version']): - return - - plugins = [p for p in cls.get_all_data() - if (p['name'] == metadata['name'] and - cls.is_updatable(p['package_version']) and - utils.major_plugin_version(metadata['version']) == - utils.major_plugin_version(p['version']))] - - plugin = None - if plugins: - # List should contain only one plugin, but just - # in case we make sure that we get plugin with - # higher version - plugin = sorted( - plugins, - key=lambda p: StrictVersion(p['version']))[0] - - return plugin - - @classmethod - def is_updatable(cls, package_version): - """Checks if plugin's package version supports updates. - - :param str package_version: package version of the plugin - :returns: True if plugin can be updated - False if plugin cannot be updated - """ - return StrictVersion('2.0.0') <= StrictVersion(package_version) - - @classmethod - def get_plugin(cls, name, version): - """Returns plugin fetched by name and version. - - :param str name: plugin name - :param str version: plugin version - :returns: dictionary with plugin data - :raises: error.BadDataException if no plugin was found - """ - plugins = [p for p in cls.get_all_data() - if (p['name'], p['version']) == (name, version)] - - if not plugins: - raise error.BadDataException( - 'Plugin "{name}" with version {version}, does ' - 'not exist'.format(name=name, version=version)) - - return plugins[0] diff --git a/fuelclient/objects/release.py b/fuelclient/objects/release.py deleted file mode 100644 index a4a91d30..00000000 --- a/fuelclient/objects/release.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from fuelclient.objects.base import BaseObject - - -class Release(BaseObject): - - class_api_path = "releases/" - instance_api_path = "releases/{0}/" - networks_path = 'releases/{0}/networks' - attributes_metadata_path = 'releases/{0}/attributes_metadata' - deployment_tasks_path = 'releases/{0}/deployment_tasks' - components_path = 'releases/{0}/components' - - def get_networks(self): - url = self.networks_path.format(self.id) - return self.connection.get_request(url) - - def update_networks(self, data): - url = self.networks_path.format(self.id) - return self.connection.put_request(url, data) - - def update_attributes_metadata(self, data): - url = self.attributes_metadata_path.format(self.id) - self.connection.put_request(url, data) - - def get_attributes_metadata(self): - url = self.attributes_metadata_path.format(self.id) - return self.connection.get_request(url) - - def get_deployment_tasks(self): - url = self.deployment_tasks_path.format(self.id) - return self.connection.get_request(url) - - def update_deployment_tasks(self, data): - url = self.deployment_tasks_path.format(self.id) - return self.connection.put_request(url, data) - - def get_components(self): - url = self.components_path.format(self.id) - return self.connection.get_request(url) diff --git a/fuelclient/objects/role.py b/fuelclient/objects/role.py deleted file mode 100644 index 1e6d7615..00000000 --- a/fuelclient/objects/role.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright 2015 Mirantis, 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. - - -from fuelclient.objects.base import BaseObject - - -class Role(BaseObject): - - instance_api_path = "{owner_type}/{owner_id}/roles/" - class_api_path = "{owner_type}/{owner_id}/roles/{role_name}/" - - def __init__(self, owner_type, owner_id, **kwargs): - super(Role, self).__init__(owner_id, **kwargs) - self.owner_type = owner_type - - def get_all(self): - return self.connection.get_request( - self.instance_api_path.format( - owner_type=self.owner_type, - owner_id=self.id)) - - def get_role(self, role_name): - return self.connection.get_request( - self.class_api_path.format( - owner_type=self.owner_type, - owner_id=self.id, - role_name=role_name)) - - def update_role(self, role_name, data): - return self.connection.put_request( - self.class_api_path.format( - owner_type=self.owner_type, - owner_id=self.id, - role_name=role_name), - data) - - def create_role(self, data): - return self.connection.post_request( - self.instance_api_path.format( - owner_type=self.owner_type, owner_id=self.id), data) - - def delete_role(self, role_name): - return self.connection.delete_request( - self.class_api_path.format( - owner_type=self.owner_type, - owner_id=self.id, - role_name=role_name)) diff --git a/fuelclient/objects/sequence.py b/fuelclient/objects/sequence.py deleted file mode 100644 index 29ec9926..00000000 --- a/fuelclient/objects/sequence.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -from fuelclient.objects.base import BaseObject - - -class Sequence(BaseObject): - - class_api_path = "sequences/" - instance_api_path = "sequences/{0}/" diff --git a/fuelclient/objects/tag.py b/fuelclient/objects/tag.py deleted file mode 100644 index 373142fb..00000000 --- a/fuelclient/objects/tag.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2016 Mirantis, 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. - - -from fuelclient.objects.base import BaseObject - - -class Tag(BaseObject): - - instance_api_path = "{owner_type}/{owner_id}/tags/" - class_api_path = "{owner_type}/{owner_id}/tags/{tag_name}/" - - def __init__(self, owner_type, owner_id, **kwargs): - super(Tag, self).__init__(owner_id, **kwargs) - self.owner_type = owner_type - - def get_all(self): - return self.connection.get_request( - self.instance_api_path.format(owner_type=self.owner_type, - owner_id=self.id)) - - def get_tag(self, tag_name): - return self.connection.get_request( - self.class_api_path.format(owner_type=self.owner_type, - owner_id=self.id, - tag_name=tag_name)) - - def update_tag(self, tag_name, data): - return self.connection.put_request( - self.class_api_path.format(owner_type=self.owner_type, - owner_id=self.id, - tag_name=tag_name), - data) - - def create_tag(self, data): - return self.connection.post_request( - self.instance_api_path.format(owner_type=self.owner_type, - owner_id=self.id), - data) - - def delete_tag(self, tag_name): - return self.connection.delete_request( - self.class_api_path.format(owner_type=self.owner_type, - owner_id=self.id, - tag_name=tag_name)) diff --git a/fuelclient/objects/task.py b/fuelclient/objects/task.py deleted file mode 100644 index 10f2226a..00000000 --- a/fuelclient/objects/task.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2014 Mirantis, 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. - -from operator import methodcaller -from time import sleep - -from fuelclient.cli.error import DeployProgressError -from fuelclient.objects.base import BaseObject - - -class Task(BaseObject): - - class_api_path = "transactions/" - instance_api_path = "transactions/{0}/" - info_types_url_map = { - 'deployment_info': 'deployment_info', - 'cluster_settings': 'settings', - 'network_configuration': 'network_configuration'} - - def delete(self, force=False): - return self.connection.delete_request( - "transactions/{0}/?force={1}".format( - self.id, - int(force), - )) - - @property - def progress(self): - return self.get_fresh_data()["progress"] - - @property - def status(self): - return self.get_fresh_data()["status"] - - @property - def is_finished(self): - return self.status in ("ready", "error") - - def wait(self): - while not self.is_finished: - sleep(0.5) - - def deployment_info(self): - return self.connection.get_request( - self._get_additional_info_url('deployment_info')) - - def network_configuration(self): - return self.connection.get_request( - self._get_additional_info_url('network_configuration')) - - def cluster_settings(self): - return self.connection.get_request( - self._get_additional_info_url('cluster_settings')) - - def _get_additional_info_url(self, info_type): - """Generate additional info url. - - :param info_type: one of deployment_info, cluster_settings, - network_configuration - :type info_type: str - :return: url - :rtype: str - """ - - return self.instance_api_path.format(self.id) +\ - self.info_types_url_map[info_type] - - -class DeployTask(Task): - - def __init__(self, obj_id, env_id): - from fuelclient.objects.environment import Environment - super(DeployTask, self).__init__(obj_id) - self.env = Environment(env_id) - self.nodes = self.env.get_all_nodes() - - @classmethod - def init_with_data(cls, data): - return cls(data["id"], data["cluster"]) - - @property - def not_finished_nodes(self): - return filter( - lambda n: not n.is_finished(latest=False), - self.nodes - ) - - @property - def is_finished(self): - return super(DeployTask, self).is_finished and all( - map( - methodcaller("is_finished"), - self.not_finished_nodes - ) - ) - - def __iter__(self): - return self - - def next(self): - if not self.is_finished: - sleep(1) - deploy_task_data = self.get_fresh_data() - if deploy_task_data["status"] == "error": - raise DeployProgressError(deploy_task_data["message"]) - for node in self.not_finished_nodes: - node.update() - return self.progress, self.nodes - else: - raise StopIteration - - -class SnapshotTask(Task): - - @classmethod - def start_snapshot_task(cls, conf): - dump_task = cls.connection.put_request("logs/package", conf) - return cls(dump_task["id"]) - - @classmethod - def get_default_config(cls): - return cls.connection.get_request("logs/package/config/default/") diff --git a/fuelclient/profiler.py b/fuelclient/profiler.py deleted file mode 100644 index df64dc0f..00000000 --- a/fuelclient/profiler.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 cProfile -import os -from pstats import Stats -import time - -from fuelclient.cli import error -from fuelclient import fuelclient_settings - - -def profiling_enabled(): - settings = fuelclient_settings.get_settings() - return bool(settings.PERFORMANCE_PROFILING_TESTS) - - -class Profiler(object): - """Runs profiler and saves results.""" - - def __init__(self, method='', handler_name=''): - self.method = method - self.handler_name = handler_name - settings = fuelclient_settings.get_settings() - self.paths = settings.PERF_TESTS_PATHS - - if not os.path.exists(self.paths['last_performance_test']): - os.makedirs(self.paths['last_performance_test']) - - self.profiler = cProfile.Profile() - self.profiler.enable() - self.start = time.time() - - def save_data(self): - try: - import gprof2dot - import pyprof2calltree - except ImportError: - msg = ('Unable to start profiling.\n Please either ' - 'disable performance profiling in settings.yaml or ' - 'install all modules listed in test-requirements.txt.') - raise error.ProfilingError(msg) - - self.profiler.disable() - elapsed = time.time() - self.start - pref_filename = os.path.join( - self.paths['last_performance_test'], - '{method:s}.{handler_name:s}.{elapsed_time:.0f}ms.{t_time}.'. - format( - method=self.method, - handler_name=self.handler_name or 'root', - elapsed_time=elapsed * 1000.0, - t_time=time.time())) - tree_file = pref_filename + 'prof' - stats_file = pref_filename + 'txt' - callgraph_file = pref_filename + 'dot' - - # write pstats - with file(stats_file, 'w') as file_o: - stats = Stats(self.profiler, stream=file_o) - stats.sort_stats('time', 'cumulative').print_stats() - - # write callgraph in dot format - parser = gprof2dot.PstatsParser(self.profiler) - - def get_function_name(args): - filename, line, name = args - module = os.path.splitext(filename)[0] - module_pieces = module.split(os.path.sep) - return "{module:s}:{line:d}:{name:s}".format( - module="/".join(module_pieces[-4:]), - line=line, - name=name) - - parser.get_function_name = get_function_name - gprof = parser.parse() - - with open(callgraph_file, 'w') as file_o: - dot = gprof2dot.DotWriter(file_o) - theme = gprof2dot.TEMPERATURE_COLORMAP - dot.graph(gprof, theme) - - # write calltree - call_tree = pyprof2calltree.CalltreeConverter(stats) - with file(tree_file, 'wb') as file_o: - call_tree.output(file_o) diff --git a/fuelclient/tests/__init__.py b/fuelclient/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/functional/__init__.py b/fuelclient/tests/functional/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/functional/base.py b/fuelclient/tests/functional/base.py deleted file mode 100644 index 0430039a..00000000 --- a/fuelclient/tests/functional/base.py +++ /dev/null @@ -1,218 +0,0 @@ -# Copyright 2013-2014 Mirantis, 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 json -import logging -import os -import re -import shutil -import subprocess -import sys -import tempfile -import time - -from fuelclient import consts -from fuelclient.objects import Release - -from oslotest import base as oslo_base - -logging.basicConfig(stream=sys.stderr) -log = logging.getLogger("CliTest.ExecutionLog") -log.setLevel(logging.DEBUG) - - -class CliExecutionResult(object): - def __init__(self, process_handle, out, err): - self.return_code = process_handle.returncode - self.stdout = out - self.stderr = err - - @property - def has_errors(self): - return self.return_code != 0 - - @property - def is_return_code_zero(self): - return self.return_code == 0 - - -class BaseTestCase(oslo_base.BaseTestCase): - - handler = '' - nailgun_root = os.environ.get('NAILGUN_ROOT', '/tmp/fuel_web/nailgun') - fuel_web_root = os.environ.get('FUEL_WEB_ROOT', '/tmp/fuel_web') - - def setUp(self): - super(BaseTestCase, self).setUp() - - self.reload_nailgun_server() - self.temp_directory = tempfile.mkdtemp() - - self.addCleanup(shutil.rmtree, self.temp_directory) - - @staticmethod - def run_command(*args, **kwargs): - handle = subprocess.Popen( - [" ".join(args)], - stdout=kwargs.pop('stdout', subprocess.PIPE), - stderr=kwargs.pop('stderr', subprocess.PIPE), - shell=kwargs.pop('shell', True), - **kwargs - ) - log.debug("Running " + " ".join(args)) - out, err = handle.communicate() - log.debug("Finished command with {0} - {1}".format(out, err)) - - def upload_command(self, cmd): - return "{0} --upload --dir {1}".format(cmd, self.temp_directory) - - def download_command(self, cmd): - return "{0} --download --dir {1}".format(cmd, self.temp_directory) - - @classmethod - def reload_nailgun_server(cls): - for action in ("dropdb", "syncdb", "loaddefault"): - cmd = 'tox -evenv -- {0}/manage.py {1}'.format( - cls.nailgun_root, action) - cls.run_command(cmd, cwd=cls.fuel_web_root) - - @classmethod - def load_data_to_nailgun_server(cls): - file_path = os.path.join(cls.nailgun_root, - 'nailgun/fixtures/sample_environment.json') - cmd = 'tox -evenv -- {0}/manage.py loaddata {1}'.format( - cls.nailgun_root, file_path) - cls.run_command(cmd, cwd=cls.fuel_web_root) - - def run_cli_command(self, command_line, handler=None, - check_errors=True, env=os.environ.copy()): - - command_args = [" ".join((handler or self.handler, command_line))] - process_handle = subprocess.Popen( - command_args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True, - env=env - ) - out, err = process_handle.communicate() - result = CliExecutionResult(process_handle, out, err) - log.debug("command_args: '%s',stdout: '%s', stderr: '%s'", - command_args[0], out, err) - if check_errors: - if not result.is_return_code_zero or result.has_errors: - self.fail(err) - return result - - def get_first_deployable_release_id(self): - releases = sorted(Release.get_all_data(), - key=lambda x: x['id']) - for r in releases: - if r['is_deployable']: - return r['id'] - self.fail("There are no deployable releases.") - - def run_cli_commands(self, command_lines, **kwargs): - for command in command_lines: - self.run_cli_command(command, **kwargs) - - def check_if_required(self, command): - call = self.run_cli_command(command, check_errors=False) - # should not work without env id - self.assertIn("required", call.stderr) - - def check_for_stdout(self, command, msg, check_errors=True): - call = self.run_cli_command(command, check_errors=check_errors) - self.assertEqual(call.stdout, msg) - - def check_for_stdout_by_regexp(self, command, pattern, check_errors=True): - call = self.run_cli_command(command, check_errors=check_errors) - result = re.search(pattern, call.stdout) - self.assertIsNotNone(result) - return result - - def check_for_stderr(self, command, msg, check_errors=True): - call = self.run_cli_command(command, check_errors=check_errors) - self.assertIn(msg, call.stderr) - - def check_all_in_msg(self, command, substrings, **kwargs): - output = self.run_cli_command(command, **kwargs) - for substring in substrings: - self.assertIn(substring, output.stdout) - - def check_for_rows_in_table(self, command): - output = self.run_cli_command(command) - message = output.stdout.split("\n") - # no env - self.assertEqual(message[2], '') - - def check_number_of_rows_in_table(self, command, number_of_rows): - output = self.run_cli_command(command) - self.assertEqual(len(output.stdout.split("\n")), number_of_rows + 3) - - def _get_task_info(self, task_id): - """Get info about task with given ID. - - :param task_id: Task ID - :type task_id: str or int - :return: Task info - :rtype: dict - """ - return {} - - def wait_task_ready(self, task_id, timeout=60, interval=3): - """Wait for changing task status to 'ready'. - - :param task_id: Task ID - :type task_id: str or int - :param timeout: Max time of waiting, in seconds - :type timeout: int - :param interval: Interval of getting task info, in seconds - :type interval: int - """ - wait_until_in_statuses = (consts.TASK_STATUSES.running, - consts.TASK_STATUSES.pending) - timer = time.time() - while True: - task = self._get_task_info(task_id) - status = task.get('status', '') - if status not in wait_until_in_statuses: - self.assertEqual(status, consts.TASK_STATUSES.ready) - break - - if time.time() - timer > timeout: - raise Exception( - "Task '{0}' seems to be hanged".format(task['name']) - ) - time.sleep(interval) - - -class CLIv1TestCase(BaseTestCase): - - handler = 'fuel' - - def _get_task_info(self, task_id): - command = "task show -f json {0}".format(str(task_id)) - call = self.run_cli_command(command, handler='fuel2') - return json.loads(call.stdout) - - -class CLIv2TestCase(BaseTestCase): - - handler = 'fuel2' - - def _get_task_info(self, task_id): - command = "task show -f json {0}".format(str(task_id)) - call = self.run_cli_command(command) - return json.loads(call.stdout) diff --git a/fuelclient/tests/functional/common/__init__.py b/fuelclient/tests/functional/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/functional/v1/__init__.py b/fuelclient/tests/functional/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/functional/v1/test_client.py b/fuelclient/tests/functional/v1/test_client.py deleted file mode 100644 index c3c1c6bc..00000000 --- a/fuelclient/tests/functional/v1/test_client.py +++ /dev/null @@ -1,516 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013-2014 Mirantis, 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 -import tempfile - -from fuelclient.tests.functional import base - - -class TestHandlers(base.CLIv1TestCase): - - def test_env_action(self): - # check env help - help_msgs = ["usage: fuel environment [-h]", - "[--list | --set | --delete | --create]", - "optional arguments:", "--help", "--list", "--set", - "--delete", "--rel", "--env-create", - "--create", "--name", "--env-name", "--nst", - "--net-segment-type"] - self.check_all_in_msg("env --help", help_msgs) - # no clusters - self.check_for_rows_in_table("env") - - for action in ("set", "create", "delete"): - self.check_if_required("env {0}".format(action)) - - release_id = self.get_first_deployable_release_id() - - # list of tuples (, ) - expected_stdout = \ - [( - "env --create --name=TestEnv --release={0}".format(release_id), - "Environment 'TestEnv' with id=1 was created!\n" - ), ( - "--env-id=1 env set --name=NewEnv", - ("Following attributes are changed for " - "the environment: name=NewEnv\n") - )] - - for cmd, msg in expected_stdout: - self.check_for_stdout(cmd, msg) - - def test_node_action(self): - help_msg = ["fuel node [-h] [--env ENV]", - "[--list | --set | --delete | --attributes |" - " --network | --disk | --deploy |" - " --hostname HOSTNAME | --name NAME |" - " --delete-from-db | --provision]", "-h", "--help", " -s", - "--default", " -d", "--download", " -u", - "--upload", "--dir", "--node", "--node-id", " -r", - "--role", "--net", "--hostname", "--name"] - self.check_all_in_msg("node --help", help_msg) - - self.check_for_rows_in_table("node") - - for action in ("set", "remove", "--network", "--disk"): - self.check_if_required("node {0}".format(action)) - - self.load_data_to_nailgun_server() - self.check_number_of_rows_in_table("node --node 9f:b6,9d:24,ab:aa", 3) - - def test_selected_node_provision(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 1 --role=controller" - )) - cmd = "--env-id=1 node --provision --node=1" - msg = "Started provisioning nodes [1].\n" - - self.check_for_stdout(cmd, msg) - - def test_help_works_without_connection(self): - fake_config = 'SERVER_ADDRESS: "333.333.333.333"' - - c_handle, c_path = tempfile.mkstemp(suffix='.json', text=True) - with open(c_path, 'w') as f: - f.write(fake_config) - - env = os.environ.copy() - env['FUELCLIENT_CUSTOM_SETTINGS'] = c_path - - try: - result = self.run_cli_command("--help", env=env) - self.assertEqual(result.return_code, 0) - finally: - os.remove(c_path) - - def test_error_when_destroying_online_node(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 1 --role=controller" - ), check_errors=False) - msg = ("Nodes with ids [1] cannot be deleted from cluster because " - "they are online. You might want to use the --force option.\n") - self.check_for_stderr( - "node --node 1 --delete-from-db", - msg, - check_errors=False - ) - - def test_force_destroy_online_node(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 1 --role=controller" - )) - msg = ("Nodes with ids [1] have been deleted from Fuel db.\n") - self.check_for_stdout( - "node --node 1 --delete-from-db --force", - msg - ) - - def test_destroy_offline_node(self): - - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - node_id = 4 - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node {0} --role=controller".format(node_id) - )) - msg = ("Nodes with ids [{0}] have been deleted from Fuel db.\n".format( - node_id)) - self.check_for_stdout( - "node --node {0} --delete-from-db".format(node_id), - msg - ) - - def test_node_change_hostname(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 2 --role=controller" - )) - msg = "Hostname for node with id 2 has been changed to test-name.\n" - self.check_for_stdout( - "node --node 2 --hostname test-name", - msg - ) - - def test_env_create_neutron_tun(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.check_for_stdout( - "env create --name=NewEnv --release={0} --nst=tun" - .format(release_id), - "Environment 'NewEnv' with id=1 was created!\n") - - def test_destroy_multiple_nodes(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 1 2 --role=controller" - )) - msg = ("Nodes with ids [1, 2] have been deleted from Fuel db.\n") - self.check_for_stdout( - "node --node 1 2 --delete-from-db --force", - msg - ) - - def test_for_examples_in_action_help(self): - actions = ( - "node", "stop", "deployment", "reset", "network", - "settings", "provisioning", "environment", "deploy-changes", - "role", "release", "snapshot", "health", "vip" - ) - for action in actions: - self.check_all_in_msg("{0} -h".format(action), ("Examples",)) - - def test_get_release_list_without_errors(self): - cmd = 'release --list' - self.run_cli_command(cmd) - - def test_reassign_node_group(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0} --nst=gre" - .format(release_id), - "--env-id=1 node set --node 1 2 --role=controller", - "nodegroup --create --env 1 --name 'new group'" - )) - msg = ['PUT http://127.0.0.1', - '/api/v1/nodes/ data=', - '"id": 1', - '"group_id": 2'] - self.check_all_in_msg( - "nodegroup --assign --group 2 --node 1 --debug", - msg - ) - - def test_node_group_creation_prints_warning_w_seg_type_vlan(self): - warn_msg = ("WARNING: In VLAN segmentation type, there will be no " - "connectivity over private network between instances " - "running on hypervisors in different segments and that " - "it's a user's responsibility to handle this " - "situation.") - - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0} --nst=vlan" - .format(release_id), - - )) - self.check_for_stderr( - "nodegroup create --name tor1 --env 1", - warn_msg, - check_errors=False - ) - - def test_create_network_group_fails_w_duplicate_name(self): - err_msg = ("(Network with name storage already exists " - "in node group default)\n") - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0} --nst=gre" - .format(release_id), - )) - self.check_for_stderr( - ("network-group --create --name storage --node-group 1 " - "--vlan 10 --cidr 10.0.0.0/24"), - err_msg, - check_errors=False - ) - - def test_create_network_group_fails_w_invalid_group(self): - err_msg = "(Node group with ID 997755 does not exist)\n" - - self.check_for_stderr( - ("network-group --create --name test --node-group 997755 " - "--vlan 10 --cidr 10.0.0.0/24"), - err_msg, - check_errors=False - ) - - -class TestCharset(base.CLIv1TestCase): - - def test_charset_problem(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=привет --release={0}".format(release_id), - "--env-id=1 node set --node 1 --role=controller", - "env" - )) - - -class TestFiles(base.CLIv1TestCase): - - def test_file_creation(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 1 --role=controller", - "--env-id=1 node set --node 2,3 --role=compute" - )) - for action in ("network", "settings"): - for format_ in ("yaml", "json"): - self.check_if_files_created( - "--env 1 {0} --download --{1}".format(action, format_), - ("{0}_1.{1}".format(action, format_),) - ) - command_to_files_map = ( - ( - "--env 1 deployment --default", - ( - "deployment_1", - "deployment_1/1.yaml", - "deployment_1/2.yaml", - "deployment_1/3.yaml" - ) - ), - ( - "--env 1 provisioning --default", - ( - "provisioning_1", - "provisioning_1/engine.yaml", - "provisioning_1/node-1.yaml", - "provisioning_1/node-2.yaml", - "provisioning_1/node-3.yaml" - ) - ), - ( - "--env 1 deployment --default --json", - ( - "deployment_1/1.json", - "deployment_1/2.json", - "deployment_1/3.json" - ) - ), - ( - "--env 1 provisioning --default --json", - ( - "provisioning_1/engine.json", - "provisioning_1/node-1.json", - "provisioning_1/node-2.json", - "provisioning_1/node-3.json" - ) - ), - ( - "node --node 1 --disk --default", - ( - "node_1", - "node_1/disks.yaml" - ) - ), - ( - "node --node 1 --network --default", - ( - "node_1", - "node_1/interfaces.yaml" - ) - ), - ( - "node --node 1 --disk --default --json", - ( - "node_1/disks.json", - ) - ), - ( - "node --node 1 --network --default --json", - ( - "node_1/interfaces.json", - ) - ) - ) - for command, files in command_to_files_map: - self.check_if_files_created(command, files) - - def check_if_files_created(self, command, paths): - command_in_dir = "{0} --dir={1}".format(command, self.temp_directory) - self.run_cli_command(command_in_dir) - for path in paths: - self.assertTrue(os.path.exists( - os.path.join(self.temp_directory, path) - )) - - -class TestDownloadUploadNodeAttributes(base.CLIv1TestCase): - - def test_upload_download_interfaces(self): - self.load_data_to_nailgun_server() - - release_id = self.get_first_deployable_release_id() - env_create = "env create --name=test --release={0}".format(release_id) - add_node = "--env-id=1 node set --node 1 --role=controller" - - cmd = "node --node-id 1 --network" - self.run_cli_commands((env_create, - add_node, - self.download_command(cmd), - self.upload_command(cmd))) - - def test_upload_download_disks(self): - self.load_data_to_nailgun_server() - cmd = "node --node-id 1 --disk" - self.run_cli_commands((self.download_command(cmd), - self.upload_command(cmd))) - - -class TestDeployChanges(base.CLIv1TestCase): - - cmd_create_env = "env create --name=test --release={0}" - cmd_add_node = "--env-id=1 node set --node 1 --role=controller" - cmd_deploy_changes = "deploy-changes --env 1" - cmd_redeploy_changes = "redeploy-changes --env 1" - - pattern_success = (r"^Deployment task with id (\d{1,}) " - r"for the environment 1 has been started.\n$") - - def setUp(self): - super(TestDeployChanges, self).setUp() - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.cmd_create_env = self.cmd_create_env.format(release_id) - self.run_cli_commands(( - self.cmd_create_env, - self.cmd_add_node - )) - - def test_deploy_changes(self): - self.check_for_stdout_by_regexp(self.cmd_deploy_changes, - self.pattern_success) - - def test_redeploy_changes(self): - result = self.check_for_stdout_by_regexp(self.cmd_deploy_changes, - self.pattern_success) - task_id = result.group(1) - self.wait_task_ready(task_id) - self.check_for_stdout_by_regexp(self.cmd_redeploy_changes, - self.pattern_success) - - -class TestDirectoryDoesntExistErrorMessages(base.CLIv1TestCase): - - def test_settings_upload(self): - self.check_for_stderr( - "settings --upload --dir /foo/bar/baz --env 1", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_deployment_upload(self): - self.check_for_stderr( - "deployment --upload --dir /foo/bar/baz --env 1", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_net_upload(self): - self.check_for_stderr( - "network --upload --dir /foo/bar/baz --env 1", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_env_download(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 2 --role=controller" - )) - self.check_for_stderr( - "network --download --dir /foo/bar/baz --env 1", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_download_network_configuration(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 2 --role=controller" - )) - self.check_for_stderr( - "--env 1 network --download --dir /foo/bar/baz", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_download_default_settings(self): - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.run_cli_commands(( - "env create --name=NewEnv --release={0}".format(release_id), - "--env-id=1 node set --node 2 --role=controller" - )) - self.check_for_stderr( - "--env 1 settings --default --dir /foo/bar/baz", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_upload_network_configuration(self): - self.check_for_stderr( - "--env 1 network --upload --dir /foo/bar/baz", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - def test_upload_network_template(self): - self.check_for_stderr( - "--env 1 network-template --upload --dir /foo/bar/baz", - "Directory '/foo/bar/baz' doesn't exist.\n", - check_errors=False - ) - - -class TestUploadSettings(base.CLIv1TestCase): - - create_env = "env create --name=test --release={0}" - add_node = "--env-id=1 node set --node 1 --role=controller" - deploy_changes = "deploy-changes --env 1" - cmd = "settings --env 1" - cmd_force = "settings --env 1 --force" - - def setUp(self): - super(TestUploadSettings, self).setUp() - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.create_env = self.create_env.format(release_id) - self.run_cli_commands(( - self.create_env, - self.add_node, - self.download_command(self.cmd) - )) - - def test_upload_settings(self): - msg_success = "Settings configuration uploaded.\n" - self.check_for_stdout(self.upload_command(self.cmd), - msg_success) diff --git a/fuelclient/tests/functional/v2/__init__.py b/fuelclient/tests/functional/v2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/functional/v2/test_client.py b/fuelclient/tests/functional/v2/test_client.py deleted file mode 100644 index 33ea9afe..00000000 --- a/fuelclient/tests/functional/v2/test_client.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013-2014 Mirantis, 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. - -from fuelclient.tests.functional import base - - -class TestDeployChanges(base.CLIv2TestCase): - - cmd_create_env = "env create -r {0} cluster-test" - cmd_add_node = "env add nodes -e 1 -n 1 -r controller" - cmd_deploy_changes = "env deploy 1" - cmd_redeploy_changes = "env redeploy 1" - - pattern_success = (r"^Deployment task with id (\d{1,}) " - r"for the environment 1 has been started.\n$") - - def setUp(self): - super(TestDeployChanges, self).setUp() - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.cmd_create_env = self.cmd_create_env.format(release_id) - self.run_cli_commands(( - self.cmd_create_env, - self.cmd_add_node - )) - - def test_deploy_changes(self): - self.check_for_stdout_by_regexp(self.cmd_deploy_changes, - self.pattern_success) - - def test_redeploy_changes(self): - result = self.check_for_stdout_by_regexp(self.cmd_deploy_changes, - self.pattern_success) - task_id = result.group(1) - self.wait_task_ready(task_id) - - self.check_for_stdout_by_regexp(self.cmd_redeploy_changes, - self.pattern_success) - - -class TestExtensionManagement(base.CLIv2TestCase): - - cmd_create_env = "env create -r {0} cluster-test-extensions-mgmt" - cmd_disable_exts = "env extension disable 1 --extensions volume_manager" - cmd_enable_exts = "env extension enable 1 --extensions volume_manager" - - pattern_enable_success = (r"^The following extensions: volume_manager " - r"have been enabled for the environment with " - r"id 1.\n$") - pattern_disable_success = (r"^The following extensions: volume_manager " - r"have been disabled for the environment with " - r"id 1.\n$") - - def setUp(self): - super(TestExtensionManagement, self).setUp() - self.load_data_to_nailgun_server() - release_id = self.get_first_deployable_release_id() - self.cmd_create_env = self.cmd_create_env.format(release_id) - self.run_cli_commands(( - self.cmd_create_env, - )) - - def test_disable_extensions(self): - self.check_for_stdout_by_regexp(self.cmd_disable_exts, - self.pattern_disable_success) - - def test_enable_extensions(self): - self.check_for_stdout_by_regexp(self.cmd_enable_exts, - self.pattern_enable_success) diff --git a/fuelclient/tests/unit/__init__.py b/fuelclient/tests/unit/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/unit/common/__init__.py b/fuelclient/tests/unit/common/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/unit/common/test_config.py b/fuelclient/tests/unit/common/test_config.py deleted file mode 100644 index 4d8f9fd7..00000000 --- a/fuelclient/tests/unit/common/test_config.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 -import sys - -import fixtures -import mock - -from fuelclient.cli import error -from fuelclient import fuelclient_settings -from fuelclient.tests.unit.v1 import base - - -class TestSettings(base.UnitTestCase): - - def setUp(self): - super(TestSettings, self).setUp() - - self.useFixture(fixtures.MockPatchObject(fuelclient_settings, - '_SETTINGS', - None)) - - @mock.patch('os.makedirs') - @mock.patch('shutil.copy') - @mock.patch('os.chmod') - @mock.patch('os.path.exists') - def test_config_generation(self, m_exists, m_chmod, m_copy, m_makedirs): - project_dir = os.path.dirname(fuelclient_settings.__file__) - - expected_fmode = 0o600 - expected_dmode = 0o700 - expected_default = os.path.join(project_dir, - 'fuel_client.yaml') - expected_path = os.path.expanduser('~/.config/fuel/fuel_client.yaml') - conf_home = os.path.expanduser('~/.config/') - conf_dir = os.path.dirname(expected_path) - - m_exists.return_value = False - f_confdir = fixtures.EnvironmentVariable('XDG_CONFIG_HOME', conf_home) - f_settings = fixtures.EnvironmentVariable('FUELCLIENT_CUSTOM_SETTINGS') - - self.useFixture(f_confdir) - self.useFixture(f_settings) - - fuelclient_settings.get_settings() - - m_makedirs.assert_called_once_with(conf_dir, expected_dmode) - m_copy.assert_called_once_with(expected_default, expected_path) - m_chmod.assert_called_once_with(expected_path, expected_fmode) - - @mock.patch('os.makedirs') - @mock.patch('os.path.exists') - def test_config_generation_write_error(self, m_exists, m_makedirs): - m_exists.return_value = False - m_makedirs.side_effect = OSError('[Errno 13] Permission denied') - - f_settings = fixtures.EnvironmentVariable('FUELCLIENT_CUSTOM_SETTINGS') - self.useFixture(f_settings) - - self.assertRaises(error.SettingsException, - fuelclient_settings.get_settings) - - @mock.patch('six.print_') - def test_deprecated_option_produces_warning(self, m_print): - expected_warings = [mock.call('DEPRECATION WARNING: LISTEN_PORT ' - 'parameter was deprecated and will not ' - 'be supported in the next version of ' - 'python-fuelclient.', end='', - file=sys.stderr), - mock.call(' Please replace this ' - 'parameter with SERVER_PORT', - file=sys.stderr)] - - m = mock.mock_open(read_data='LISTEN_PORT: 9000') - with mock.patch('fuelclient.fuelclient_settings.open', m): - fuelclient_settings.get_settings() - - m_print.assert_has_calls(expected_warings, any_order=False) - - @mock.patch('six.print_') - def test_both_deprecated_and_new_options_produce_warning(self, m_print): - expected_waring = ('WARNING: configuration contains both ' - 'LISTEN_PORT and SERVER_PORT options set. Since ' - 'LISTEN_PORT was deprecated, only the value of ' - 'SERVER_PORT will be used.') - - m = mock.mock_open(read_data='LISTEN_PORT: 9000\nSERVER_PORT: 9000') - with mock.patch('fuelclient.fuelclient_settings.open', m): - fuelclient_settings.get_settings() - - m_print.assert_has_calls([mock.call(expected_waring, file=sys.stderr)]) - - @mock.patch('six.print_') - def test_set_deprecated_option_overwrites_unset_new_option(self, m_print): - m = mock.mock_open(read_data='KEYSTONE_PASS: "admin"\n' - 'OS_PASSWORD:\n') - with mock.patch('fuelclient.fuelclient_settings.open', m): - settings = fuelclient_settings.get_settings() - - self.assertEqual('admin', settings.OS_PASSWORD) - self.assertNotIn('OS_PASSWORD', settings.config) - - def test_fallback_to_deprecated_option(self): - m = mock.mock_open(read_data='LISTEN_PORT: 9000') - with mock.patch('fuelclient.fuelclient_settings.open', m): - settings = fuelclient_settings.get_settings() - - self.assertEqual(9000, settings.LISTEN_PORT) - - def test_update_from_cli_params(self): - test_config_text = ('SERVER_ADDRESS: "127.0.0.1"\n' - 'SERVER_PORT: "8000"\n' - 'OS_USERNAME: "admin"\n' - 'OS_PASSWORD:\n' - 'OS_TENANT_NAME:\n') - - test_parsed_args = mock.Mock(os_password='test_password', - server_port="3000", - os_username=None) - del test_parsed_args.server_address - del test_parsed_args.os_tenant_name - - m = mock.mock_open(read_data=test_config_text) - with mock.patch('fuelclient.fuelclient_settings.open', m): - settings = fuelclient_settings.get_settings() - - settings.update_from_command_line_options(test_parsed_args) - - self.assertEqual('3000', settings.SERVER_PORT) - self.assertEqual('test_password', settings.OS_PASSWORD) - self.assertEqual('admin', settings.OS_USERNAME) diff --git a/fuelclient/tests/unit/common/test_environments.py b/fuelclient/tests/unit/common/test_environments.py deleted file mode 100644 index da319639..00000000 --- a/fuelclient/tests/unit/common/test_environments.py +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock -import os - -from fuelclient import objects - -from fuelclient.tests.unit.v1 import base - - -class TestEnvironmentObject(base.UnitTestCase): - - def setUp(self): - super(TestEnvironmentObject, self).setUp() - self.env_object = objects.Environment(1) - - def _setup_os_mock(self, os_mock): - os_mock.path.exists.return_value = False - os_mock.path.join = os.path.join - os_mock.path.abspath = lambda x: x - - @mock.patch("fuelclient.objects.environment.os") - def test_write_facts_to_dir_for_legacy_envs(self, os_mock): - facts = [ - { - "uid": "1", - "role": "controller", - "data": "data1" - }, - { - "uid": "2", - "role": "compute", - "data": "data2" - }, - ] - - self._setup_os_mock(os_mock) - serializer = mock.MagicMock() - - self.env_object.write_facts_to_dir( - "deployment", facts, serializer=serializer - ) - - serializer.write_to_path.assert_has_calls( - [ - mock.call("./deployment_1/controller_1", facts[0]), - mock.call("./deployment_1/compute_2", facts[1]) - ] - ) - - @mock.patch("fuelclient.objects.environment.os") - def test_write_facts_to_dir_for_new_envs(self, os_mock): - facts = [ - { - "uid": "1", - "roles": ["controller"], - "data": "data1" - }, - { - "uid": "2", - "roles": ["compute"], - "data": "data2" - }, - ] - - self._setup_os_mock(os_mock) - serializer = mock.MagicMock() - - self.env_object.write_facts_to_dir( - "deployment", facts, serializer=serializer - ) - - serializer.write_to_path.assert_has_calls( - [ - mock.call("./deployment_1/1", facts[0]), - mock.call("./deployment_1/2", facts[1]) - ] - ) - - @mock.patch("fuelclient.objects.environment.os") - def test_write_facts_to_dir_if_facts_is_dict(self, os_mock): - facts = { - "engine": "test_engine", - "nodes": [ - { - "uid": "1", - "name": "node-1", - "roles": ["controller"], - "data": "data1" - }, - { - "uid": "2", - "name": "node-2", - "roles": ["compute"], - "data": "data2" - }, - ] - } - - self._setup_os_mock(os_mock) - serializer = mock.MagicMock() - - self.env_object.write_facts_to_dir( - "deployment", facts, serializer=serializer - ) - - serializer.write_to_path.assert_has_calls( - [ - mock.call("./deployment_1/engine", facts['engine']), - mock.call("./deployment_1/node-1", facts['nodes'][0]), - mock.call("./deployment_1/node-2", facts['nodes'][1]) - ] - ) diff --git a/fuelclient/tests/unit/common/test_network_template.py b/fuelclient/tests/unit/common/test_network_template.py deleted file mode 100644 index 60a2f72a..00000000 --- a/fuelclient/tests/unit/common/test_network_template.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 json -import mock -import six -import yaml - -from fuelclient.tests.unit.v1 import base - -YAML_TEMPLATE = """adv_net_template: - default: - network_assignments: - fuelweb_admin: - ep: br-fw-admin - management: - ep: br-mgmt - private: - ep: br-prv - public: - ep: br-ex - storage: - ep: br-storage - nic_mapping: - default: - if1: eth0 - templates_for_node_role: - ceph-osd: - - common - - storage - compute: - - common - - private - - storage - controller: - - public - - private - - storage - - common -""" - -JSON_TEMPLATE = """{ - "adv_net_template": { - "default": { - "nic_mapping": { - "default": { - "if1": "eth0" - } - }, - "templates_for_node_role": { - "controller": [ - "public", - "private", - "storage", - "common" - ], - "compute": [ - "common", - "private", - "storage" - ], - "ceph-osd": [ - "common", - "storage" - ] - }, - "network_assignments": { - "storage": { - "ep": "br-storage" - }, - "private": { - "ep": "br-prv" - }, - "public": { - "ep": "br-ex" - }, - "management": { - "ep": "br-mgmt" - }, - "fuelweb_admin": { - "ep": "br-fw-admin" - } - } - } - } -} -""" - - -class TestNetworkTemplate(base.UnitTestCase): - def setUp(self): - super(TestNetworkTemplate, self).setUp() - - self.env_id = 42 - self.req_path = ('/api/v1/clusters/{0}/network_configuration/' - 'template'.format(self.env_id)) - - def test_upload_action(self): - mput = self.m_request.put(self.req_path, json={}) - test_command = [ - 'fuel', 'network-template', '--env', str(self.env_id), '--upload'] - - m_open = mock.mock_open(read_data=YAML_TEMPLATE) - with mock.patch('fuelclient.cli.serializers.open', - m_open, - create=True): - self.execute(test_command) - - self.assertTrue(mput.called) - self.assertEqual(mput.last_request.json(), json.loads(JSON_TEMPLATE)) - m_open().read.assert_called_once_with() - - def test_download_action(self): - mget = self.m_request.get(self.req_path, text=JSON_TEMPLATE) - - test_command = [ - 'fuel', 'network-template', '--env', str(self.env_id), - '--download'] - - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', m_open, - create=True): - self.execute(test_command) - - self.assertTrue(mget.called) - - written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0]) - expected_yaml = yaml.safe_load(YAML_TEMPLATE) - self.assertEqual(written_yaml, expected_yaml) - - def test_delete_action(self): - mdelete = self.m_request.delete(self.req_path, json={}) - - cmd = ['fuel', 'network-template', '--env', str(self.env_id), - '--delete'] - - with mock.patch('sys.stdout', new=six.StringIO()) as m_out: - self.execute(cmd) - - self.assertTrue(mdelete.called) - - msg = ("Network template configuration for environment id={0}" - " has been deleted.".format(self.env_id)) - self.assertIn(msg, m_out.getvalue()) diff --git a/fuelclient/tests/unit/common/test_release.py b/fuelclient/tests/unit/common/test_release.py deleted file mode 100644 index d024a9e6..00000000 --- a/fuelclient/tests/unit/common/test_release.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient.commands.release import ReleaseComponentList -from fuelclient.tests.unit.v1 import base - - -class TestReleaseComponent(base.UnitTestCase): - - def test_retrieve_predicates(self): - predicates = ('any_of', 'all_of', 'one_of', 'none_of') - items = { - "items": ["fake:component:1", - "fake:component:2"] - } - - for predicate in predicates: - test_data = {predicate: items} - real_data = ReleaseComponentList.retrieve_predicates(test_data) - expected_data = "{} (fake:component:1, fake:component:2)".format( - predicate) - self.assertEqual(expected_data, real_data) - - def test_retrieve_predicates_w_wrong_predicate(self): - test_data = { - "bad_predicate": { - "items": ["fake:component:1", - "fake:component:2"], - } - } - - self.assertRaisesRegexp(ValueError, - "Predicates not found.", - ReleaseComponentList.retrieve_predicates, - test_data) - - def test_retrieve_data(self): - test_data = "fake:component:1" - real_data = ReleaseComponentList.retrieve_data(test_data) - self.assertEqual("fake:component:1", real_data) - - test_data = [{"name": "fake:component:1"}] - real_data = ReleaseComponentList.retrieve_data(test_data) - self.assertEqual("fake:component:1", real_data) - - test_data = [ - { - "one_of": { - "items": ["fake:component:1"] - } - }, - { - "any_of": { - "items": ["fake:component:1", - "fake:component:2"] - } - }, - { - "all_of": { - "items": ["fake:component:1", - "fake:component:2"] - } - }, - { - "none_of": { - "items": ["fake:component:1"] - } - } - ] - real_data = ReleaseComponentList.retrieve_data(test_data) - expected_data = ("one_of (fake:component:1), " - "any_of (fake:component:1, fake:component:2), " - "all_of (fake:component:1, fake:component:2), " - "none_of (fake:component:1)") - self.assertEqual(expected_data, real_data) diff --git a/fuelclient/tests/unit/common/test_serializers.py b/fuelclient/tests/unit/common/test_serializers.py deleted file mode 100644 index 13163adb..00000000 --- a/fuelclient/tests/unit/common/test_serializers.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 json - -import mock -import yaml - -from fuelclient.cli import error -from fuelclient.cli.serializers import Serializer -from fuelclient.tests.unit.v1 import base - - -class TestSerializers(base.UnitTestCase): - - DATA = { - 'a': 1, - 'b': { - 'c': [2, 3, 4], - 'd': 'string', - } - } - - def test_get_from_params(self): - params_to_formats = ( - ('yaml', 'yaml'), - ('json', 'json'), - ('xyz', Serializer.default_format), - ) - for param, format in params_to_formats: - params = mock.Mock(serialization_format=format) - serializer = Serializer.from_params(params) - self.assertEqual(serializer.format, format) - - def test_serialize(self): - deserializers = {'json': json.loads, 'yaml': yaml.load} - for format, deserialize in deserializers.items(): - serialized = Serializer(format).serialize(self.DATA) - self.assertEqual(self.DATA, deserialize(serialized)) - - def test_deserialize(self): - serializers = {'json': json.dumps, 'yaml': yaml.safe_dump} - for format, serialize in serializers.items(): - serialized = serialize(self.DATA) - deserialized = Serializer(format).deserialize(serialized) - self.assertEqual(self.DATA, deserialized) - - def test_deserialize_fail(self): - - broken_data = '{foo: bar: buzz:}' - for format in ('json', 'yaml'): - self.assertRaises(error.BadDataException, - Serializer(format).deserialize, broken_data) - - def test_write_to_path_invalid_file_exception(self): - serializer = Serializer('json') - mo = mock.mock_open() - with mock.patch('__main__.open', mo, create=True) as mocked_open: - mocked_open.side_effect = IOError() - self.assertRaises(error.InvalidFileException, - serializer.write_to_path, - '/foo/bar/baz', self.DATA) diff --git a/fuelclient/tests/unit/common/test_settings.py b/fuelclient/tests/unit/common/test_settings.py deleted file mode 100644 index 0cdad63e..00000000 --- a/fuelclient/tests/unit/common/test_settings.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - -from mock import mock_open -from mock import patch - -from fuelclient.tests.unit.v1 import base - - -YAML_SETTINGS_DATA = """editable: - access: - user: - value: test_user -""" -JSON_SETTINGS_DATA = { - 'editable': { - 'access': { - 'user': { - 'value': 'test_user' - } - } - } -} - - -class BaseSettings(base.UnitTestCase): - - def check_upload_action(self, test_command, test_url): - m = mock_open(read_data=YAML_SETTINGS_DATA) - put = self.m_request.put(test_url, json={}) - - with patch('six.moves.builtins.open', m, create=True): - self.execute(test_command) - - m().read.assert_called_once_with() - self.assertTrue(put.called) - self.assertDictEqual(put.last_request.json(), JSON_SETTINGS_DATA) - - def check_default_action(self, test_command, test_url): - m = mock_open() - get = self.m_request.get(test_url, json=JSON_SETTINGS_DATA) - - with patch('six.moves.builtins.open', m, create=True): - self.execute(test_command) - - self.assertTrue(get.called) - m().write.assert_called_once_with(YAML_SETTINGS_DATA) - - def check_download_action(self, test_command, test_url): - m = mock_open() - get = self.m_request.get(test_url, json=JSON_SETTINGS_DATA) - - with patch('six.moves.builtins.open', m, create=True): - self.execute(test_command) - - m().write.assert_called_once_with(YAML_SETTINGS_DATA) - self.assertTrue(get.called) - - -class TestSettings(BaseSettings): - - def test_upload_action(self): - self.check_upload_action( - test_command=[ - 'fuel', 'settings', '--env', '1', '--upload'], - test_url='/api/v1/clusters/1/attributes') - - def test_upload_force_action(self): - self.check_upload_action( - test_command=[ - 'fuel', 'settings', '--env', '1', '--upload', '--force'], - test_url='/api/v1/clusters/1/attributes?force=1') - - def test_default_action(self): - self.check_default_action( - test_command=[ - 'fuel', 'settings', '--env', '1', '--default'], - test_url='/api/v1/clusters/1/attributes/defaults') - - def test_download_action(self): - self.check_download_action( - test_command=[ - 'fuel', 'settings', '--env', '1', '--download'], - test_url='/api/v1/clusters/1/attributes') diff --git a/fuelclient/tests/unit/common/test_utils.py b/fuelclient/tests/unit/common/test_utils.py deleted file mode 100644 index 34c0cb2b..00000000 --- a/fuelclient/tests/unit/common/test_utils.py +++ /dev/null @@ -1,331 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 json -import os -import six -import subprocess -import yaml - -import mock -import requests - -from fuelclient.cli import error -from fuelclient import client -from fuelclient.common import data_utils -from fuelclient.tests.unit.v1 import base -from fuelclient import utils - - -class TestUtils(base.UnitTestCase): - - @mock.patch('fuelclient.utils.os.walk') - def test_iterfiles(self, mwalk): - mwalk.return_value = [ - ('/some_directory/', [], ['valid.yaml', 'invalid.yml'])] - - pattern = '*.yaml' - directory = '/some_directory' - - expected_result = [os.path.join(directory, 'valid.yaml')] - files = list(utils.iterfiles(directory, pattern)) - - mwalk.assert_called_once_with(directory, followlinks=True) - self.assertEqual(expected_result, files) - - def make_process_mock(self, return_code=0): - process_mock = mock.Mock() - process_mock.stdout = ['Stdout line 1', 'Stdout line 2'] - process_mock.returncode = return_code - - return process_mock - - def test_exec_cmd(self): - cmd = 'some command' - - process_mock = self.make_process_mock() - with mock.patch.object( - subprocess, 'Popen', return_value=process_mock) as popen_mock: - utils.exec_cmd(cmd) - - popen_mock.assert_called_once_with( - cmd, - stdout=None, - stderr=subprocess.STDOUT, - shell=True, - cwd=None) - - def test_exec_cmd_raises_error(self): - cmd = 'some command' - return_code = 1 - - process_mock = self.make_process_mock(return_code=return_code) - - with mock.patch.object( - subprocess, 'Popen', return_value=process_mock) as popen_mock: - self.assertRaisesRegexp( - error.ExecutedErrorNonZeroExitCode, - 'Shell command executed with "{0}" ' - 'exit code: {1} '.format(return_code, cmd), - utils.exec_cmd, cmd) - - popen_mock.assert_called_once_with( - cmd, - stdout=None, - stderr=subprocess.STDOUT, - shell=True, - cwd=None) - - def test_exec_cmd_iterator(self): - cmd = 'some command' - - process_mock = self.make_process_mock() - with mock.patch.object( - subprocess, 'Popen', return_value=process_mock) as popen_mock: - for line in utils.exec_cmd_iterator(cmd): - self.assertTrue(line.startswith('Stdout line ')) - - popen_mock.assert_called_once_with( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True) - - def test_exec_cmd_iterator_raises_error(self): - cmd = 'some command' - return_code = 1 - - process_mock = self.make_process_mock(return_code=return_code) - with mock.patch.object(subprocess, 'Popen', return_value=process_mock): - with self.assertRaisesRegexp( - error.ExecutedErrorNonZeroExitCode, - 'Shell command executed with "{0}" ' - 'exit code: {1} '.format(return_code, cmd)): - for line in utils.exec_cmd_iterator(cmd): - self.assertTrue(line.startswith('Stdout line ')) - - def test_parse_yaml_file(self): - mock_open = self.mock_open("key: value") - - with mock.patch('fuelclient.utils.io.open', mock_open): - self.assertEqual( - utils.parse_yaml_file('some_file_name'), - {'key': 'value'}) - - @mock.patch('fuelclient.utils.glob.iglob', - return_value=['file1', 'file2']) - @mock.patch('fuelclient.utils.parse_yaml_file', - side_effect=['content_file1', 'content_file2']) - def test_glob_and_parse_yaml(self, parse_mock, iglob_mock): - path = '/tmp/path/mask*' - - content = [] - for data in utils.glob_and_parse_yaml(path): - content.append(data) - - iglob_mock.assert_called_once_with(path) - self.assertEqual( - parse_mock.call_args_list, - [mock.call('file1'), - mock.call('file2')]) - - self.assertEqual(content, ['content_file1', 'content_file2']) - - def test_major_plugin_version(self): - pairs = [ - ['1.2.3', '1.2'], - ['123456789.123456789.12121', '123456789.123456789'], - ['1.2', '1.2']] - - for arg, expected in pairs: - self.assertEqual( - utils.major_plugin_version(arg), - expected) - - @mock.patch('fuelclient.utils.os.path.lexists', side_effect=[True, False]) - def test_file_exists(self, lexists_mock): - self.assertTrue(utils.file_exists('file1')) - self.assertFalse(utils.file_exists('file2')) - - self.assertEqual( - lexists_mock.call_args_list, - [mock.call('file1'), mock.call('file2')]) - - def test_get_error_body_get_from_json(self): - error_body = 'This is error body' - - body_json = json.dumps({ - 'message': error_body - }) - if isinstance(body_json, six.text_type): - body_json = body_json.encode('utf-8') - - resp = requests.Response() - resp._content = body_json - - exception = requests.HTTPError() - exception.response = resp - - self.assertEqual(error.get_error_body(exception), error_body) - - def test_get_error_body_get_from_plaintext(self): - error_body = b'This is error body' - - resp = requests.Response() - resp._content = error_body - - exception = requests.HTTPError() - exception.response = resp - - self.assertEqual(error.get_error_body(exception), - error_body.decode('utf-8')) - - def test_get_display_data_single(self): - test_data = {'a': 1, 'b': [], 'c': [1, 2, 3], 'd': 4} - fields = ('a', 'b', 'c') - - result = data_utils.get_display_data_single(fields, test_data) - self.assertEqual([1, [], [1, 2, 3]], result) - - def test_get_display_data_bad_key(self): - test_data = {'a': 1, 'b': 2, 'c': 3} - fields = ('b', 'bad_key') - self.assertEqual( - [2, None], - data_utils.get_display_data_single(fields, test_data) - ) - - def test_get_display_data_multi(self): - test_data = [{'a': 1, 'b': 2, 'c': 3}, {'b': 8, 'c': 9}] - fields = ('b', 'c') - - result = data_utils.get_display_data_multi(fields, test_data) - self.assertEqual([[2, 3], [8, 9]], result) - - @mock.patch('sys.getfilesystemencoding', return_value='utf-8') - def test_str_to_unicode(self, _): - test_data = 'тест' - expected_data = test_data if six.PY3 else u'тест' - result = utils.str_to_unicode(test_data) - self.assertIsInstance(result, six.text_type) - self.assertEqual(result, expected_data) - - @mock.patch('fuelclient.utils.sys') - def test_latin_str_to_unicode(self, sys_mock): - sys_mock.getfilesystemencoding.return_value = 'iso-8859-16' - - test_data = 'czegoś' if six.PY3 else u'czegoś'.encode('iso-8859-16') - expected_data = test_data if six.PY3 else u'czegoś' - result = utils.str_to_unicode(test_data) - self.assertIsInstance(result, six.text_type) - self.assertEqual(result, expected_data) - - def test_HTTP_error_message(self): - text = 'message text' - - self.m_request.post('/api/v1/address', - json={'message': text}, - status_code=403) - - with self.assertRaisesRegexp(error.HTTPError, - '403.*{}'.format(text)): - client.DefaultAPIClient.post_request('address') - - def test_parse_to_list_of_dicts(self): - items = utils.parse_to_list_of_dicts([{"id": 1}]) - self.assertEqual(items, [{"id": 1}]) - - items = utils.parse_to_list_of_dicts([{"id": 2}, {"id": 3}]) - self.assertEqual(items, [{"id": 2}, {"id": 3}]) - - items = utils.parse_to_list_of_dicts([[{"id": 4}]]) - self.assertEqual(items, [{"id": 4}]) - - items = utils.parse_to_list_of_dicts( - [[{"id": 5}, {"id": 6}], {"id": 7}]) - self.assertEqual(items, [{"id": 5}, {"id": 6}, {"id": 7}]) - - self.assertRaisesRegexp( - TypeError, 'A dict or list instance expected', - utils.parse_to_list_of_dicts, [42]) - - def test_safe_load_json(self): - test_data = {'test_key': 'test_val'} - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.tests.unit.common.test_utils.open', - m_open): - stream = open('/a/random/file', 'r') - loaded = data_utils.safe_load('json', stream) - - self.assertEqual(test_data, loaded) - - def test_safe_load_yaml(self): - test_data = {'test_key': 'test_val'} - - m_open = mock.mock_open(read_data=yaml.dump(test_data)) - with mock.patch('fuelclient.tests.unit.common.test_utils.open', - m_open): - stream = open('/a/random/file', 'r') - loaded = data_utils.safe_load('yaml', stream) - - self.assertEqual(test_data, loaded) - - @mock.patch('json.dump') - def test_safe_dump_json(self, m_dump): - test_data = {'test_key': 'test_val'} - - m_open = mock.mock_open() - with mock.patch('fuelclient.tests.unit.common.test_utils.open', - m_open): - stream = open('/a/random/file', 'w') - data_utils.safe_dump('json', stream, test_data) - - m_dump.assert_called_once_with(test_data, stream, indent=4) - - @mock.patch('yaml.safe_dump') - def test_safe_dump_yaml(self, m_dump): - test_data = {'test_key': 'test_val'} - - m_open = mock.mock_open() - with mock.patch('fuelclient.tests.unit.common.test_utils.open', - m_open): - stream = open('/a/random/file', 'w') - data_utils.safe_dump('yaml', stream, test_data) - - m_dump.assert_called_once_with(test_data, - stream, - default_flow_style=False) - - def test_safe_dump_wrong_format(self): - test_data = {'test_key': 'test_val'} - - m_open = mock.mock_open() - with mock.patch('fuelclient.tests.unit.common.test_utils.open', - m_open): - stream = open('/a/random/file', 'w') - self.assertRaises(ValueError, - data_utils.safe_dump, - 'bad', stream, test_data) - - def test_safe_load_wrong_format(self): - m_open = mock.mock_open() - with mock.patch('fuelclient.tests.unit.common.test_utils.open', - m_open): - stream = open('/a/random/file', 'w') - self.assertRaises(ValueError, - data_utils.safe_load, - 'bad', stream) diff --git a/fuelclient/tests/unit/v1/__init__.py b/fuelclient/tests/unit/v1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/unit/v1/base.py b/fuelclient/tests/unit/v1/base.py deleted file mode 100644 index 71d3f8e7..00000000 --- a/fuelclient/tests/unit/v1/base.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2013-2015 Mirantis, 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 mock -from oslotest import base as oslo_base -import requests_mock as rm -import six - -from fuelclient.cli import parser - - -class FakeFile(six.StringIO): - """Context manager for a fake file - - NOTE(eli): We cannot use mock_open from mock library - here, because it hangs when we use 'with' statement, - and when we want to read file by chunks. - - """ - def __enter__(self): - return self - - def __exit__(self, *args): - pass - - -class UnitTestCase(oslo_base.BaseTestCase): - """Base test class which does not require nailgun server to run.""" - - def setUp(self): - super(UnitTestCase, self).setUp() - - self.auth_required_patcher = mock.patch('fuelclient.client.' - 'APIClient.auth_required', - new_callable=mock.PropertyMock) - - self.auth_required_mock = self.auth_required_patcher.start() - self.auth_required_mock.return_value = False - - self.m_request = rm.Mocker() - self.m_request.start() - - self.addCleanup(self.auth_required_patcher.stop) - self.addCleanup(self.m_request.stop) - - def execute(self, command): - """Execute old CLI.""" - - return parser.main(command) - - def mock_open(self, text, filename='some.file'): - """Mocks builtin open function - - Usage example: - - with mock.patch('__builtin__.open', self.mock_open('file content')): - # call mocked code - """ - fileobj = FakeFile(text) - setattr(fileobj, 'name', filename) - return mock.MagicMock(return_value=fileobj) diff --git a/fuelclient/tests/unit/v1/test_attributes_actions.py b/fuelclient/tests/unit/v1/test_attributes_actions.py deleted file mode 100644 index 4b33107d..00000000 --- a/fuelclient/tests/unit/v1/test_attributes_actions.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - -from mock import patch - -from fuelclient.tests.unit.v1 import base - - -@patch('fuelclient.cli.serializers.open', create=True) -@patch('fuelclient.cli.actions.base.os') -class TestClusterAttributesActions(base.UnitTestCase): - - _input = { - 'editable': { - 'test': 'foo', - }} - - _output = 'editable:\n test: foo\n' - - def test_attributes_download(self, mos, mopen): - get = self.m_request.get('/api/v1/clusters/1/attributes', - json=self._input) - - self.execute( - ['fuel', 'env', '--env', '1', '--attributes', '--download']) - - self.assertTrue(get.called) - - mopen().__enter__().write.assert_called_once_with(self._output) - - def test_attributes_upload(self, mos, mopen): - mopen().__enter__().read.return_value = self._output - put = self.m_request.put('/api/v1/clusters/1/attributes', json={}) - - self.execute( - ['fuel', 'env', '--env', '1', '--attributes', '--upload']) - - self.assertTrue(put.called) - self.assertEqual(put.last_request.json(), self._input) diff --git a/fuelclient/tests/unit/v1/test_authentication.py b/fuelclient/tests/unit/v1/test_authentication.py deleted file mode 100644 index 5e1948c2..00000000 --- a/fuelclient/tests/unit/v1/test_authentication.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2013-2014 Mirantis, 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 fixtures -import mock - -from fuelclient import fuelclient_settings -from fuelclient.tests.unit.v1 import base - - -@mock.patch('keystoneclient.v2_0.client.Client', - return_value=mock.Mock(auth_token='')) -class TestAuthentication(base.UnitTestCase): - - def setUp(self): - super(TestAuthentication, self).setUp() - - self.auth_required_mock.return_value = True - self.m_request.get('/api/v1/nodes/', json={}) - - self.useFixture(fixtures.MockPatchObject(fuelclient_settings, - '_SETTINGS', - None)) - - def validate_credentials_response(self, m_client, username=None, - password=None, tenant_name=None): - """Checks whether keystone was called properly.""" - - conf = fuelclient_settings.get_settings() - - expected_url = 'http://{}:{}{}'.format(conf.SERVER_ADDRESS, - conf.SERVER_PORT, - '/keystone/v2.0') - m_client.__init__assert_called_once_with(auth_url=expected_url, - username=username, - password=password, - tenant_name=tenant_name) - - def test_credentials_settings(self, mkeystone_cli): - self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME')) - self.useFixture(fixtures.EnvironmentVariable('OS_PASSWORD')) - self.useFixture(fixtures.EnvironmentVariable('OS_TENANT_NAME')) - - conf = fuelclient_settings.get_settings() - conf.config['OS_USERNAME'] = 'test_user' - conf.config['OS_PASSWORD'] = 'test_password' - conf.config['OS_TENANT_NAME'] = 'test_tenant_name' - - self.execute(['fuel', 'node']) - self.validate_credentials_response(mkeystone_cli, - username='test_user', - password='test_password', - tenant_name='test_tenant_name') - - def test_credentials_cli(self, mkeystone_cli): - self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME')) - self.useFixture(fixtures.EnvironmentVariable('OS_PASSWORD')) - self.useFixture(fixtures.EnvironmentVariable('OS_TENANT_NAME')) - - self.execute(['fuel', '--os-username=a', '--os-tenant-name=admin', - '--os-password=b', 'node']) - self.validate_credentials_response(mkeystone_cli, - username='a', - password='b', - tenant_name='admin') - - def test_authentication_env_variables(self, mkeystone_cli): - self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME', 'name')) - self.useFixture(fixtures.EnvironmentVariable('OS_PASSWORD', 'pass')) - self.useFixture(fixtures.EnvironmentVariable('OS_TENANT_NAME', 'ten')) - - self.execute(['fuel', 'node']) - self.validate_credentials_response(mkeystone_cli, - username='name', - password='pass', - tenant_name='ten') - - def test_credentials_override(self, mkeystone_cli): - self.useFixture(fixtures.EnvironmentVariable('OS_USERNAME')) - self.useFixture(fixtures.EnvironmentVariable('OS_PASSWORD', 'var_p')) - self.useFixture(fixtures.EnvironmentVariable('OS_TENANT_NAME', 'va_t')) - - conf = fuelclient_settings.get_settings() - conf.config['OS_USERNAME'] = 'conf_user' - conf.config['OS_PASSWORD'] = 'conf_password' - conf.config['OS_TENANT_NAME'] = 'conf_tenant_name' - - self.execute(['fuel', '--os-tenant-name=cli_tenant', 'node']) - self.validate_credentials_response(mkeystone_cli, - username='conf_user', - password='var_p', - tenant_name='cli_tenant') diff --git a/fuelclient/tests/unit/v1/test_base_action.py b/fuelclient/tests/unit/v1/test_base_action.py deleted file mode 100644 index 22eabbe4..00000000 --- a/fuelclient/tests/unit/v1/test_base_action.py +++ /dev/null @@ -1,78 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 mock -from six import moves - -from fuelclient.cli.actions import base -from fuelclient.cli import error -from fuelclient.tests.unit.v1 import base as base_tests - - -class TestBaseAction(base_tests.UnitTestCase): - - def setUp(self): - super(TestBaseAction, self).setUp() - self.action = base.Action() - - @mock.patch('fuelclient.cli.actions.base.os') - def test_default_directory_with_param(self, m_os): - directory = 'some/dir' - self.action.default_directory(directory) - m_os.path.abspath.assert_called_once_with(directory) - - @mock.patch('fuelclient.cli.actions.base.os') - def test_default_directory_without_param(self, m_os): - self.action.default_directory() - m_os.path.abspath.assert_called_once_with(m_os.curdir) - - @mock.patch('fuelclient.cli.actions.base.os.mkdir') - @mock.patch('fuelclient.cli.actions.base.os.path.exists') - def test_full_path_directory(self, m_exists, m_mkdir): - m_exists.return_value = False - self.assertEqual( - self.action.full_path_directory('/base/path', 'subdir'), - '/base/path/subdir' - ) - m_mkdir.assert_called_once_with('/base/path/subdir') - - @mock.patch('fuelclient.cli.actions.base.os') - def test_full_path_directory_no_access(self, m_os): - exc_msg = 'Bas permissions' - m_os.path.exists.return_value = False - m_os.mkdir.side_effect = OSError(exc_msg) - - with self.assertRaisesRegexp(error.ActionException, exc_msg): - self.action.full_path_directory('/base/path', 'subdir') - - @mock.patch('fuelclient.cli.actions.base.os') - def test_full_path_directory_already_exists(self, m_os): - m_os.path.exists.return_value = True - self.action.full_path_directory('/base/path', 'subdir') - self.assertEqual(m_os.mkdir.call_count, 0) - - -class TestExtraArguments(base_tests.UnitTestCase): - - def test_error_on_extra_arguments(self): - err_msg = 'unrecognized arguments: extraarg1 extraarg2\n' - - with mock.patch('sys.stderr', new=moves.cStringIO()) as m_stderr: - self.assertRaises( - SystemExit, self.execute, - ['fuel', 'nodegroup', '--delete', 'extraarg1', 'extraarg2']) - - self.assertIn(err_msg, m_stderr.getvalue()) diff --git a/fuelclient/tests/unit/v1/test_deployment_history_action.py b/fuelclient/tests/unit/v1/test_deployment_history_action.py deleted file mode 100644 index 7e30ee1c..00000000 --- a/fuelclient/tests/unit/v1/test_deployment_history_action.py +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2016 Mirantis, 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. - -from mock import patch - -from fuelclient.cli.formatting import format_table -from fuelclient.cli.serializers import Serializer -from fuelclient.tests.unit.v1 import base -from fuelclient.tests import utils -from fuelclient.v1.deployment_history import DeploymentHistoryClient - - -class TestDeploymentTasksAction(base.UnitTestCase): - - @patch.object(Serializer, 'print_to_output') - def test_show_full_history(self, print_mock): - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'nodes=&' - 'statuses=&' - 'tasks_names=', - json=utils.get_fake_deployment_history()) - - self.execute( - ['fuel', 'deployment-tasks', '--tid', '1'] - ) - print_mock.assert_called_once_with( - utils.get_fake_deployment_history(convert_legacy_fields=True), - format_table( - utils.get_fake_deployment_history(convert_legacy_fields=True), - acceptable_keys=DeploymentHistoryClient.history_records_keys)) - - @patch.object(Serializer, 'print_to_output') - def test_show_full_history_include_summary(self, print_mock): - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'nodes=&' - 'statuses=&' - 'include_summary=1&' - 'tasks_names=', - json=utils.get_fake_deployment_history(include_summary=True)) - - self.execute( - ['fuel', 'deployment-tasks', '--tid', '1', '--include-summary'] - ) - print_mock.assert_called_once_with( - utils.get_fake_deployment_history(convert_legacy_fields=True, - include_summary=True), - format_table( - utils.get_fake_deployment_history(convert_legacy_fields=True, - include_summary=True), - acceptable_keys=(DeploymentHistoryClient.history_records_keys + - ('summary',)))) - - @patch.object(Serializer, 'print_to_output') - def test_show_tasks_history_with_parameters(self, print_mock): - tasks_after_facade = [ - { - 'task_name': 'controller-remaining-tasks', - 'task_parameters': 'parameters: {puppet_manifest: /etc/puppet/' - 'modules/osnailyfacter/modular/globals/' - 'globals.pp,\n puppet_modules: /etc/' - 'puppet/modules, timeout: 3600}\nrole: ' - '[controller]\ntype: puppet\nversion: 2.0.0' - '\n', - 'status_by_node': '1 - ready - 2016-03-25T17:22:10 - ' - '2016-03-25T17:22:30\n' - '2 - ready - 2016-03-25T17:22:10 - ' - '2016-03-25T17:22:30' - }, - { - 'task_name': 'pending-task', - 'task_parameters': 'parameters: {puppet_manifest: /etc/puppet/' - 'modules/osnailyfacter/modular/globals/' - 'globals.pp,\n puppet_modules: /etc/puppet' - '/modules, timeout: 3600}\nrole: ' - '[controller]\ntype: puppet\nversion: 2.0.0' - '\n', - 'status_by_node': '1 - pending - not started - not ended\n' - '2 - pending - not started - not ended' - } - ] - - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'nodes=&' - 'statuses=&' - 'tasks_names=controller-remaining-tasks,pending-task', - json=utils.get_fake_deployment_history(add_task_data=True)) - - self.execute( - ['fuel', 'deployment-tasks', - '--tid', '1', - '--task-name', 'controller-remaining-tasks,pending-task', - '--node', '1,2', - '--show-parameters'] - ) - print_mock.assert_called_once_with( - tasks_after_facade, - format_table( - tasks_after_facade, - acceptable_keys=DeploymentHistoryClient.tasks_records_keys)) - - def test_show_history_for_special_nodes(self): - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'nodes=1,2', - json={}) - - self.execute( - ['fuel', 'deployment-tasks', '--tid', '1', - '--node-id', '1,2'] - ) - - self.assertEqual(self.m_history_api.call_count, 1) - - def test_show_history_for_special_tasks(self): - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'tasks_names=test1,test2', - json={}) - - self.execute( - ['fuel', 'deployment-tasks', '--tid', '1', - '--task-name', 'test1,test2'] - ) - - self.assertEqual(self.m_history_api.call_count, 1) - - def test_show_history_with_special_statuses(self): - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'statuses=ready,skipped', - json={}) - self.execute( - ['fuel', 'deployment-tasks', '--tid', '1', - '--status', 'ready,skipped'] - ) - self.assertEqual(self.m_history_api.call_count, 1) - - def test_show_history_for_special_statuses_nodes_and_tasks(self): - self.m_history_api = self.m_request.get( - '/api/v1/transactions/1/deployment_history/?' - 'nodes=1,2&' - 'statuses=ready,skipped&' - 'tasks_names=test1,test2', - json={}) - self.execute( - ['fuel', 'deployment-tasks', '--tid', '1', - '--status', 'ready,skipped', '--node', '1,2', - '--task-name', 'test1,test2'] - ) - self.assertEqual(self.m_history_api.call_count, 1) diff --git a/fuelclient/tests/unit/v1/test_deployment_tasks_actions.py b/fuelclient/tests/unit/v1/test_deployment_tasks_actions.py deleted file mode 100644 index c8c92ba3..00000000 --- a/fuelclient/tests/unit/v1/test_deployment_tasks_actions.py +++ /dev/null @@ -1,134 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 - -from mock import patch -import requests_mock as rm - -from fuelclient.tests.unit.v1 import base - - -API_INPUT = [{'id': 'primary-controller'}] -API_OUTPUT = '- id: primary-controller\n' -RELEASE_OUTPUT = [{'id': 1, 'version': '2014.2-6.0', 'name': 'Something'}] -MULTIPLE_RELEASES = [{'id': 1, 'version': '2014.2-6.0', 'name': 'Something'}, - {'id': 2, 'version': '2014.3-6.1', 'name': 'Something'}] - - -@patch('fuelclient.cli.serializers.open', create=True) -@patch('fuelclient.cli.actions.base.os') -class TestReleaseDeploymentTasksActions(base.UnitTestCase): - - def test_release_tasks_download(self, mos, mopen): - self.m_request.get(rm.ANY, json=API_INPUT) - self.execute( - ['fuel', 'rel', '--rel', '1', '--deployment-tasks', '--download']) - mopen().__enter__().write.assert_called_once_with(API_OUTPUT) - - def test_release_tasks_upload(self, mos, mopen): - mopen().__enter__().read.return_value = API_OUTPUT - put = self.m_request.put('/api/v1/releases/1/deployment_tasks', - json=API_OUTPUT) - - self.execute( - ['fuel', 'rel', '--rel', '1', '--deployment-tasks', '--upload']) - - self.assertTrue(put.called) - self.assertEqual(put.last_request.json(), API_INPUT) - - -@patch('fuelclient.cli.serializers.open', create=True) -@patch('fuelclient.cli.actions.base.os') -class TestClusterDeploymentTasksActions(base.UnitTestCase): - - def test_cluster_tasks_download(self, mos, mopen): - self.m_request.get(rm.ANY, json=API_INPUT) - self.execute( - ['fuel', 'env', '--env', '1', '--deployment-tasks', '--download']) - mopen().__enter__().write.assert_called_once_with(API_OUTPUT) - - def test_cluster_tasks_upload(self, mos, mopen): - mopen().__enter__().read.return_value = API_OUTPUT - put = self.m_request.put('/api/v1/clusters/1/deployment_tasks', - json=API_OUTPUT) - - self.execute( - ['fuel', 'env', '--env', '1', '--deployment-tasks', '--upload']) - - self.assertTrue(put.called) - self.assertEqual(put.last_request.json(), API_INPUT) - - -@patch('fuelclient.cli.serializers.open', create=True) -@patch('fuelclient.utils.iterfiles') -class TestSyncDeploymentTasks(base.UnitTestCase): - - def test_sync_deployment_scripts(self, mfiles, mopen): - self.m_request.get(rm.ANY, json=RELEASE_OUTPUT) - put = self.m_request.put('/api/v1/releases/1/deployment_tasks', - json={}) - - mfiles.return_value = ['/etc/puppet/2014.2-6.0/tasks.yaml'] - mopen().__enter__().read.return_value = API_OUTPUT - file_pattern = '*tests*' - self.execute( - ['fuel', 'rel', '--sync-deployment-tasks', '--fp', file_pattern]) - - mfiles.assert_called_once_with( - os.path.realpath(os.curdir), file_pattern) - - self.assertTrue(put.called) - self.assertEqual(put.last_request.json(), API_INPUT) - - @patch('fuelclient.cli.actions.release.os') - def test_sync_with_directory_path(self, mos, mfiles, mopen): - self.m_request.get(rm.ANY, json=RELEASE_OUTPUT) - put = self.m_request.put('/api/v1/releases/1/deployment_tasks', - json={}) - - mos.path.realpath.return_value = real_path = '/etc/puppet' - mfiles.return_value = [real_path + '/2014.2-6.0/tasks.yaml'] - mopen().__enter__().read.return_value = API_OUTPUT - self.execute( - ['fuel', 'rel', '--sync-deployment-tasks', '--dir', real_path]) - mfiles.assert_called_once_with(real_path, '*tasks.yaml') - self.assertTrue(put.called) - - def test_multiple_tasks_but_one_release(self, mfiles, mopen): - self.m_request.get(rm.ANY, json=RELEASE_OUTPUT) - put = self.m_request.put(rm.ANY, json={}) - - mfiles.return_value = ['/etc/puppet/2014.2-6.0/tasks.yaml', - '/etc/puppet/2014.3-6.1/tasks.yaml'] - mopen().__enter__().read.return_value = API_OUTPUT - - self.execute( - ['fuel', 'rel', '--sync-deployment-tasks']) - - self.assertEqual(put.call_count, 1) - - def test_multiple_releases(self, mfiles, mopen): - self.m_request.get(rm.ANY, json=MULTIPLE_RELEASES) - put = self.m_request.put(rm.ANY, json={}) - mfiles.return_value = ['/etc/puppet/2014.2-6.0/tasks.yaml', - '/etc/puppet/2014.3-6.1/tasks.yaml'] - mopen().__enter__().read.return_value = API_OUTPUT - - self.execute( - ['fuel', 'rel', '--sync-deployment-tasks']) - - self.assertEqual(put.call_count, 2) diff --git a/fuelclient/tests/unit/v1/test_environment.py b/fuelclient/tests/unit/v1/test_environment.py deleted file mode 100644 index 26803a3d..00000000 --- a/fuelclient/tests/unit/v1/test_environment.py +++ /dev/null @@ -1,194 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 mock -import requests_mock as rm -from six import moves - -from fuelclient.objects.environment import Environment -from fuelclient.tests.unit.v1 import base - - -class TestEnvironment(base.UnitTestCase): - - def test_delete_operational_wo_force(self): - cluster_id = 1 - url = '/api/v1/clusters/{0}/'.format(cluster_id) - cmd = 'fuel --env {0} env delete'.format(cluster_id) - - self.m_request.get(url, - json={'id': cluster_id, 'status': 'operational'}) - m_delete = self.m_request.delete(url) - - with mock.patch('sys.stdout', new=moves.cStringIO()) as m_stdout: - self.execute(cmd.split()) - self.assertIn('--force', m_stdout.getvalue()) - - self.assertFalse(m_delete.called) - - def test_neutron_gre_using_warning(self): - cluster_id = 1 - cluster_data = { - 'id': cluster_id, - 'name': 'test', - } - self.m_request.post('/api/v1/clusters/', json=cluster_data) - self.m_request.get('/api/v1/clusters/{0}/'.format(cluster_id), - json=cluster_data) - - with mock.patch('sys.stderr', new=moves.cStringIO()) as m_stderr: - self.execute( - 'fuel env create --name test --rel 1 --nst gre' - .split() - ) - - self.assertIn("WARNING: GRE network segmentation type is " - "deprecated since 7.0 release.", - m_stderr.getvalue()) - - @mock.patch('fuelclient.objects.task.DeployTask.init_with_data') - def test_deploy_changes(self, task_data): - dry_run = False - noop_run = False - mdeploy = self.m_request.put('/api/v1/clusters/1/changes' - '?dry_run={0}&noop_run={1}'.format( - int(dry_run), int(noop_run)), json={}) - - cmd = ['fuel', 'deploy-changes', '--env', '1'] - self.execute(cmd) - self.check_deploy_redeploy_changes(dry_run, mdeploy) - - @mock.patch('fuelclient.objects.task.DeployTask.init_with_data') - def test_deploy_changes_dry_run(self, task_data): - dry_run = True - mdeploy = self.m_request.put('/api/v1/clusters/1/changes' - '?dry_run={0}'.format( - int(dry_run)), json={}) - - cmd = ['fuel', 'deploy-changes', '--env', '1'] - - cmd.append('--dry-run') - self.execute(cmd) - self.check_deploy_redeploy_changes(dry_run, mdeploy) - - @mock.patch('fuelclient.objects.task.DeployTask.init_with_data') - def test_redeploy_changes(self, task_data): - dry_run = False - mdeploy = self.m_request.put('/api/v1/clusters/1/changes/redeploy' - '?dry_run={0}'.format( - int(dry_run)), json={}) - - cmd = ['fuel', 'redeploy-changes', '--env', '1'] - - self.execute(cmd) - self.check_deploy_redeploy_changes(dry_run, mdeploy) - - @mock.patch('fuelclient.objects.task.DeployTask.init_with_data') - def test_redeploy_changes_dry_run(self, task_data): - dry_run = True - mdeploy = self.m_request.put('/api/v1/clusters/1/changes/redeploy' - '?dry_run={0}'.format( - int(dry_run)), json={}) - - cmd = ['fuel', 'redeploy-changes', '--env', '1'] - - cmd.append('--dry-run') - self.execute(cmd) - self.check_deploy_redeploy_changes(dry_run, mdeploy) - - def check_deploy_redeploy_changes(self, res, mdeploy, mode='dry_run'): - self.assertEqual(mdeploy.last_request.qs[mode][0], - str(int(res))) - - -class TestEnvironmentOstf(base.UnitTestCase): - - def setUp(self): - super(TestEnvironmentOstf, self).setUp() - - self.env = Environment(None) - - @mock.patch.object(Environment.connection, 'post_request', mock.Mock( - return_value=[ - {'id': 1}, - {'id': 2}, ])) - def test_run_test_sets(self): - self.assertEqual(self.env._testruns_ids, []) - - testruns = self.env.run_test_sets(['sanity', 'ha']) - - self.assertEqual(len(testruns), 2) - self.assertIn(1, self.env._testruns_ids) - self.assertIn(2, self.env._testruns_ids) - - @mock.patch.object(Environment.connection, 'post_request') - def test_credentials_are_passed_to_ostf(self, post_request): - self.env.run_test_sets(['sanity'], {'tenant': 't1', - 'username': 'u1', - 'password': 'p1'}) - run_test_request = post_request.call_args[0][1] - self.assertTrue(len(run_test_request) > 0, 'Got empty request') - self.assertIn('metadata', run_test_request[0]) - self.assertIn('ostf_os_access_creds', run_test_request[0]['metadata']) - creds = run_test_request[0]['metadata']['ostf_os_access_creds'] - self.assertEqual(creds['ostf_os_tenant_name'], 't1') - self.assertEqual(creds['ostf_os_username'], 'u1') - self.assertEqual(creds['ostf_os_password'], 'p1') - - @mock.patch.object(Environment.connection, 'get_request', mock.Mock( - side_effect=[ - {'id': 1, 'status': 'running'}, - {'id': 2, 'status': 'finished'}, ])) - def test_get_state_of_tests(self): - self.env._testruns_ids.extend([1, 2]) - tests = self.env.get_state_of_tests() - - self.env.connection.get_request.assert_has_calls([ - mock.call('testruns/1', ostf=True), - mock.call('testruns/2', ostf=True)]) - self.assertEqual(tests, [ - {'id': 1, 'status': 'running'}, - {'id': 2, 'status': 'finished'}]) - - def test_get_deployment_tasks_with_end(self): - end = 'task1' - get = self.m_request.get(rm.ANY, json={}) - - self.env.get_deployment_tasks(end=end) - - self.assertEqual(get.last_request.qs, {'end': ['task1']}) - - def test_get_default_facts(self): - legacy_format_facts = [ - {"uid": "1", "a": 1}, {"uid": "2", "a": 1} - ] - new_format_facts = [ - {"uid": "common", "a": 1}, {"uid": "1"}, {"uid": "2"} - ] - self.m_request.get( - '/api/v1/clusters/{0}/orchestrator/deployment/defaults/?split=0' - .format(self.env.id), - json=legacy_format_facts - ) - self.m_request.get( - '/api/v1/clusters/{0}/orchestrator/deployment/defaults/?split=1' - .format(self.env.id), - json=new_format_facts - ) - facts = self.env.get_default_facts("deployment", split=False) - self.assertItemsEqual(legacy_format_facts, facts) - facts = self.env.get_default_facts("deployment", split=True) - self.assertItemsEqual(new_format_facts, facts) diff --git a/fuelclient/tests/unit/v1/test_fuel_version.py b/fuelclient/tests/unit/v1/test_fuel_version.py deleted file mode 100644 index f906263b..00000000 --- a/fuelclient/tests/unit/v1/test_fuel_version.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright 2015 Mirantis, 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 json -import mock -import yaml - -from fuelclient.tests.unit.v1 import base -from fuelclient.tests.utils import fake_fuel_version - - -class TestFuelVersion(base.UnitTestCase): - - def test_return_yaml(self): - self.m_request.get('/api/v1/version/', - json=fake_fuel_version.get_fake_fuel_version()) - - with mock.patch('sys.stdout') as mstdout: - self.execute(['fuel', 'fuel-version', '--yaml']) - args, _ = mstdout.write.call_args_list[0] - regex = ('No JSON object could be decoded' - '|Expecting value: line 1 column 1') - with self.assertRaisesRegexp(ValueError, regex): - json.loads(args[0]) - self.assertEqual( - fake_fuel_version.get_fake_fuel_version(), - yaml.safe_load(args[0])) - - def test_return_json(self): - self.m_request.get('/api/v1/version/', - json=fake_fuel_version.get_fake_fuel_version()) - - with mock.patch('sys.stdout') as mstdout: - self.execute(['fuel', 'fuel-version', '--json']) - args, _ = mstdout.write.call_args_list[0] - self.assertEqual( - fake_fuel_version.get_fake_fuel_version(), - json.loads(args[0])) diff --git a/fuelclient/tests/unit/v1/test_graph_action.py b/fuelclient/tests/unit/v1/test_graph_action.py deleted file mode 100644 index e3eb2450..00000000 --- a/fuelclient/tests/unit/v1/test_graph_action.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 io -import os - -import mock - -from fuelclient.cli.actions import graph -from fuelclient.tests.unit.v1 import base - - -GRAPH_API_OUTPUT = "digraph G { A -> B -> C }" -TASKS_API_OUTPUT = [ - {'id': 'primary-controller'}, - {'id': 'sync-time'}, -] - - -class TestGraphAction(base.UnitTestCase): - - def setUp(self): - super(TestGraphAction, self).setUp() - self.m_tasks_api = self.m_request.get( - '/api/v1/clusters/1/deployment_tasks', - json=TASKS_API_OUTPUT) - self.m_graph_api = self.m_request.get( - '/api/v1/clusters/1/deploy_tasks/graph.gv', - text=GRAPH_API_OUTPUT) - - self.m_full_path = mock.patch.object(graph.GraphAction, - 'full_path_directory').start() - self.m_full_path.return_value = '/path' - - def tearDown(self): - super(TestGraphAction, self).tearDown() - self.m_full_path.stop() - - def test_download_all_tasks(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', '--download'] - ) - - querystring = self.m_graph_api.last_request.qs - for task in TASKS_API_OUTPUT: - self.assertIn(task['id'], querystring['tasks'][0]) - self.assertIn(GRAPH_API_OUTPUT, m_stdout.getvalue()) - - def test_download_selected_tasks(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', - '--tasks', 'task-a', 'task-b'] - ) - - querystring = self.m_graph_api.last_request.qs - self.assertIn('task-a', querystring['tasks'][0]) - self.assertIn('task-b', querystring['tasks'][0]) - self.assertIn(GRAPH_API_OUTPUT, m_stdout.getvalue()) - - def test_download_with_skip(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', - '--skip', 'sync-time', 'task-b'] - ) - querystring = self.m_graph_api.last_request.qs - self.assertIn('primary-controller', querystring['tasks'][0]) - self.assertNotIn('sync-time', querystring['tasks'][0]) - self.assertNotIn('task-b', querystring['tasks'][0]) - self.assertIn(GRAPH_API_OUTPUT, m_stdout.getvalue()) - - def test_download_with_end_and_start(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', - '--start', 'task-a', '--end', 'task-b'] - ) - - tasks_qs = self.m_tasks_api.last_request.qs - self.assertEqual('task-a', tasks_qs['start'][0]) - self.assertEqual('task-b', tasks_qs['end'][0]) - - graph_qs = self.m_graph_api.last_request.qs - for task in TASKS_API_OUTPUT: - self.assertIn(task['id'], graph_qs['tasks'][0]) - self.assertIn(GRAPH_API_OUTPUT, m_stdout.getvalue()) - - def test_download_only_parents(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', - '--parents-for', 'task-z'] - ) - querystring = self.m_graph_api.last_request.qs - self.assertEqual('task-z', querystring['parents_for'][0]) - self.assertIn(GRAPH_API_OUTPUT, m_stdout.getvalue()) - - def test_download_with_removed(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', - '--remove', 'skipped'] - ) - querystring = self.m_graph_api.last_request.qs - self.assertEqual('skipped', querystring['remove'][0]) - self.assertIn(GRAPH_API_OUTPUT, m_stdout.getvalue()) - - def test_params_saved_in_dotfile(self): - with mock.patch('sys.stdout', new=io.StringIO()) as m_stdout: - self.execute( - ['fuel', 'graph', '--download', '--env', '1', - '--parents-for', 'task-z', - '--skip', 'task-a'] - ) - saved_params = ("# params:\n" - "# - start: None\n" - "# - end: None\n" - "# - skip: ['task-a']\n" - "# - tasks: []\n" - "# - parents-for: task-z\n" - "# - remove: []\n") - self.assertIn(saved_params + GRAPH_API_OUTPUT, m_stdout.getvalue()) - - @mock.patch('fuelclient.cli.actions.graph.open', create=True) - @mock.patch('fuelclient.cli.actions.graph.render_graph') - @mock.patch('fuelclient.cli.actions.graph.os.access') - @mock.patch('fuelclient.cli.actions.graph.os.path.exists') - def test_render(self, m_exists, m_access, m_render, m_open): - graph_data = 'some-dot-data' - m_exists.return_value = True - m_open().__enter__().read.return_value = graph_data - - self.execute( - ['fuel', 'graph', '--render', 'graph.gv'] - ) - - m_open.assert_called_with('graph.gv', 'r') - m_render.assert_called_once_with( - graph_data, '/path/graph.gv.png', False) - - @mock.patch('fuelclient.cli.actions.graph.open', create=True) - @mock.patch('fuelclient.cli.actions.graph.render_graph') - @mock.patch('fuelclient.cli.actions.graph.os.access') - @mock.patch('fuelclient.cli.actions.graph.os.path.exists') - def test_render_with_tred(self, m_exists, m_access, m_render, m_open): - graph_data = 'some-dot-data' - m_exists.return_value = True - m_open().__enter__().read.return_value = graph_data - - self.execute( - ['fuel', 'graph', '--render', 'graph.gv', '--tred'] - ) - - m_open.assert_called_with('graph.gv', 'r') - m_render.assert_called_once_with( - graph_data, '/path/graph.gv.png', True) - - @mock.patch('fuelclient.cli.actions.graph.os.path.exists') - def test_render_no_file(self, m_exists): - m_exists.return_value = False - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'graph', '--render', 'graph.gv']) - - @mock.patch('fuelclient.cli.actions.graph.open', create=True) - @mock.patch('fuelclient.cli.actions.graph.render_graph') - @mock.patch('fuelclient.cli.actions.graph.os.access') - @mock.patch('fuelclient.cli.actions.graph.os.path.exists') - def test_render_with_output_path(self, m_exists, m_access, m_render, - m_open): - output_dir = '/output/dir' - graph_data = 'some-dot-data' - m_exists.return_value = True - m_open().__enter__().read.return_value = graph_data - self.m_full_path.return_value = output_dir - - self.execute( - ['fuel', 'graph', '--render', 'graph.gv', '--dir', output_dir] - ) - - self.m_full_path.assert_called_once_with(output_dir, '') - m_render.assert_called_once_with( - graph_data, '/output/dir/graph.gv.png', False) - - @mock.patch('fuelclient.cli.actions.graph.open', create=True) - @mock.patch('fuelclient.cli.actions.graph.render_graph') - @mock.patch('fuelclient.cli.actions.graph.os.access') - @mock.patch('fuelclient.cli.actions.graph.os.path.exists') - def test_render_with_output_path_with_tred( - self, m_exists, m_access, m_render, m_open): - output_dir = '/output/dir' - graph_data = 'some-dot-data' - m_exists.return_value = True - m_open().__enter__().read.return_value = graph_data - self.m_full_path.return_value = output_dir - - self.execute( - ['fuel', 'graph', '--render', 'graph.gv', '--dir', output_dir, - '--tred'] - ) - - self.m_full_path.assert_called_once_with(output_dir, '') - m_render.assert_called_once_with( - graph_data, '/output/dir/graph.gv.png', True) - - @mock.patch('fuelclient.cli.actions.graph.os.access') - @mock.patch('fuelclient.cli.actions.graph.render_graph') - def test_render_from_stdin(self, m_render, m_access): - graph_data = u'graph data' - - with mock.patch('sys.stdin', new=io.StringIO(graph_data)): - self.execute( - ['fuel', 'graph', '--render', '-', ] - ) - - m_render.assert_called_once_with( - graph_data, '/path/graph.gv.png', False) - - @mock.patch('fuelclient.cli.actions.graph.os.access') - @mock.patch('fuelclient.cli.actions.graph.render_graph') - def test_render_from_stdin_with_tred(self, m_render, m_access): - graph_data = u'graph data' - - with mock.patch('sys.stdin', new=io.StringIO(graph_data)): - self.execute( - ['fuel', 'graph', '--render', '-', '--tred'] - ) - - m_render.assert_called_once_with( - graph_data, '/path/graph.gv.png', True) - - @mock.patch('fuelclient.cli.actions.graph.open', create=True) - @mock.patch('fuelclient.cli.actions.graph.os.path.exists') - @mock.patch('fuelclient.cli.actions.graph.os.access') - def test_render_no_access_to_output(self, m_access, m_exists, m_open): - m_exists.return_value = True - m_access.return_value = False - output_dir = '/output/dir' - self.m_full_path.return_value = output_dir - - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'graph', '--render', - 'graph.gv', '--dir', output_dir]) - m_access.assert_called_once_with(output_dir, os.W_OK) diff --git a/fuelclient/tests/unit/v1/test_network_groups.py b/fuelclient/tests/unit/v1/test_network_groups.py deleted file mode 100644 index fcacd941..00000000 --- a/fuelclient/tests/unit/v1/test_network_groups.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright 2015 Mirantis, 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 mock - -from fuelclient.tests.unit.v1 import base -from fuelclient.tests.utils import fake_network_group - - -class TestNetworkGroupActions(base.UnitTestCase): - - def setUp(self): - super(TestNetworkGroupActions, self).setUp() - - self.env_id = 42 - self.req_base_path = '/api/v1/networks/' - - self.ng = fake_network_group.get_fake_network_group() - - def test_list_network_groups(self): - mget = self.m_request.get(self.req_base_path, json={}) - list_commands = [ - ['fuel', 'network-group', '--list'], ['fuel', 'network-group']] - - for cmd in list_commands: - self.execute(cmd) - self.assertTrue(mget.called) - - def test_list_network_groups_filtering(self): - mget = self.m_request.get(self.req_base_path, json={}) - - self.execute( - ['fuel', 'network-group', '--node-group', str(self.ng['id'])] - ) - - self.assertTrue(mget.called) - - def create_network_group(self, cmd): - mpost = self.m_request.post(self.req_base_path, json={ - 'id': self.ng['id'], - 'name': self.ng['name'], - }) - self.execute(cmd) - - call_data = mpost.last_request.json() - self.assertEqual(self.ng['id'], call_data['group_id']) - self.assertEqual(self.ng['name'], call_data['name']) - - self.assertTrue(mpost.called) - - return call_data - - def test_create_network_group(self): - cmd = ['fuel', 'network-group', '--create', '--cidr', self.ng['cidr'], - '--name', self.ng['name'], '--node-group', str(self.ng['id'])] - self.create_network_group(cmd) - - def test_create_network_group_w_meta(self): - cmd = ['fuel', 'network-group', '--create', '--cidr', self.ng['cidr'], - '--name', self.ng['name'], '--node-group', str(self.ng['id']), - '--meta', '{"ip_ranges": ["10.0.0.2", "10.0.0.254"]}'] - self.create_network_group(cmd) - - meta = self.m_request.last_request.json()['meta'] - self.assertEqual(meta['ip_ranges'], ["10.0.0.2", "10.0.0.254"]) - - def test_create_network_group_required_args(self): - with mock.patch("sys.stderr") as m_stderr: - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'network-group', '--create']) - - self.assertIn('--nodegroup", "--name" and "--cidr" required!', - m_stderr.write.call_args[0][0]) - - def test_delete_network_group_required_args(self): - with mock.patch("sys.stderr") as m_stderr: - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'network-group', '--delete']) - - self.assertIn('"--network" required!', m_stderr.write.call_args[0][0]) - - def test_delete_network_group(self): - path = self.req_base_path + str(self.env_id) + '/' - mdelete = self.m_request.delete(path, status_code=204) - self.execute( - ['fuel', 'network-group', '--delete', - '--network', str(self.env_id)]) - - self.assertTrue(mdelete.called) - - def test_network_group_duplicate_name(self): - mpost = self.m_request.post(self.req_base_path, status_code=409) - - with mock.patch("sys.stderr") as m_stderr: - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'network-group', '--create', '--cidr', - self.ng['cidr'], '--name', self.ng['name'], - '--node-group', str(self.ng['id'])]) - - self.assertIn("409 Client Error", m_stderr.write.call_args[0][0]) - self.assertTrue(mpost.called) - - def test_set_network_group(self): - path = self.req_base_path + str(self.env_id) + '/' - mput = self.m_request.put(path, json={}) - self.execute([ - 'fuel', 'network-group', '--set', '--network', str(self.ng['id']), - '--name', self.ng['name']]) - - self.assertTrue(mput.called) - - def test_set_network_group_meta(self): - path = self.req_base_path + str(self.env_id) + '/' - mput = self.m_request.put(path, json={}) - self.execute([ - 'fuel', 'network-group', '--set', '--network', str(self.ng['id']), - '--meta', '{"ip_ranges": ["10.0.0.2", "10.0.0.254"]}']) - - self.assertTrue(mput.called) - - meta = self.m_request.last_request.json()['meta'] - self.assertEqual(meta['ip_ranges'], ["10.0.0.2", "10.0.0.254"]) diff --git a/fuelclient/tests/unit/v1/test_networks_action.py b/fuelclient/tests/unit/v1/test_networks_action.py deleted file mode 100644 index 8fb6ed1e..00000000 --- a/fuelclient/tests/unit/v1/test_networks_action.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 yaml - -from mock import patch - -from fuelclient.tests.unit.v1 import base - - -ENV_OUTPUT = { - 'id': 1, - 'net_provider': 'neutron', -} - -FILE_INPUT = '''networks: -- name: public -- id: 1 -''' - -NETWORK_CONFIG_OK_OUTPUT = { - 'status': 'ready', - 'progress': 100, -} - -NETWORK_CONFIG_ERROR_OUTPUT = { - 'message': 'Some error', - 'errors': [], -} - - -@patch('fuelclient.cli.serializers.open', create=True) -@patch('fuelclient.cli.actions.base.os') -class TestNetworkActions(base.UnitTestCase): - - def test_network_download(self, mos, mopen): - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - self.m_request.get('/api/v1/clusters/1/network_configuration/neutron', - json=yaml.load(FILE_INPUT)) - self.execute(['fuel', 'network', '--env', '1', '--download']) - mopen().__enter__().write.assert_called_once_with(FILE_INPUT) - - def test_network_upload(self, mos, mopen): - mopen().__enter__().read.return_value = FILE_INPUT - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - mneutron_put = self.m_request.put( - '/api/v1/clusters/1/network_configuration/neutron', - json=NETWORK_CONFIG_OK_OUTPUT) - self.execute(['fuel', 'network', '--env', '1', '--upload']) - self.assertEqual(mneutron_put.call_count, 1) - url = mneutron_put.request_history[0].url - self.assertIn('clusters/1/network_configuration/neutron', url) - - def test_network_upload_with_error(self, mos, mopen): - mopen().__enter__().read.return_value = FILE_INPUT - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - self.m_request.put( - '/api/v1/clusters/1/network_configuration/neutron', - status_code=400, json=NETWORK_CONFIG_ERROR_OUTPUT) - - with patch("sys.stderr") as m_stderr: - self.assertRaises( - SystemExit, self.execute, - ['fuel', 'network', '--env', '1', '--upload']) - - self.assertIn("400 Client Error", m_stderr.write.call_args[0][0]) - self.assertIn(NETWORK_CONFIG_ERROR_OUTPUT['message'], - m_stderr.write.call_args[0][0]) diff --git a/fuelclient/tests/unit/v1/test_nodegroups.py b/fuelclient/tests/unit/v1/test_nodegroups.py deleted file mode 100644 index f8e22ed3..00000000 --- a/fuelclient/tests/unit/v1/test_nodegroups.py +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright 2015 Mirantis, 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 mock -from six import StringIO - -from fuelclient.tests.unit.v1 import base -from fuelclient.tests import utils - - -class TestNodeGroupActions(base.UnitTestCase): - - def setUp(self): - super(TestNodeGroupActions, self).setUp() - - self.env = utils.get_fake_env() - self.req_base_path = '/api/v1/nodegroups/' - self.ng = utils.get_fake_node_group() - self.ngs = utils.get_fake_node_groups() - - def test_list_nodegroups(self): - mget = self.m_request.get(self.req_base_path, json=self.ngs) - self.execute(['fuel', 'nodegroup', '--list']) - - self.assertTrue(mget.called) - - def test_create_nodegroup(self): - neutron_url = \ - '/api/v1/clusters/{0}/network_configuration/neutron'.format( - self.env['id'] - ) - - self.m_request.get('/api/v1/clusters/{0[id]}/'.format(self.env), - json={'id': self.env['id']}) - mpost = self.m_request.post(self.req_base_path, - json={'id': self.ng['id'], - 'name': self.ng['name']}) - mget = self.m_request.get(neutron_url, - json={'networking_parameters': {}}) - with mock.patch('sys.stdout', new=StringIO()) as m_stdout: - self.execute([ - 'fuel', 'nodegroup', '--create', - '--name', self.ng['name'], '--env', str(self.env['id']) - ]) - - msg = "Node group '{name}' with id={id} "\ - "in environment {cluster} was created!" - self.assertIn( - msg.format(cluster=self.env['id'], **self.ng), - m_stdout.getvalue() - ) - - call_data = mpost.last_request.json() - self.assertEqual(self.env['id'], call_data['cluster_id']) - self.assertEqual(self.ng['name'], call_data['name']) - - self.assertTrue(mget.called) - - def _check_required_message_for_commands(self, err_msg, commands): - for cmd in commands: - with mock.patch("sys.stderr") as m_stderr: - self.assertRaises(SystemExit, self.execute, cmd) - - m_stderr.write.assert_called_with(err_msg) - - def test_create_nodegroup_arguments_required(self): - err_msg = '"--env" and "--name" required!\n' - - env_not_present = ['fuel', 'nodegroup', '--create', - '--name', 'test'] - - name_not_present = ['fuel', '--env', str(self.env['id']), - 'nodegroup', '--create'] - - self._check_required_message_for_commands( - err_msg, (env_not_present, name_not_present)) - - def test_delete_nodegroup(self): - path = self.req_base_path + str(self.env['id']) + '/' - mget = self.m_request.get(path, json={'name': 'test group'}) - delete_path = self.req_base_path + str(self.env['id']) + '/' - mdelete = self.m_request.delete(delete_path, status_code=204) - ngid = self.env['id'] - with mock.patch('sys.stdout', new=StringIO()) as m_stdout: - self.execute(['fuel', 'nodegroup', '--delete', '--group', - str(ngid)]) - msg = u"Node group with id={id} was deleted!" - self.assertIn( - msg.format(id=ngid), - m_stdout.getvalue() - ) - - self.assertTrue(mget.called) - self.assertTrue(mdelete.called) - - def test_delete_nodegroup_group_arg_required(self): - err_msg = '"--group" required!\n' - self._check_required_message_for_commands( - err_msg, - (['fuel', 'nodegroup', '--delete'],) - ) - - def test_assign_nodegroup_fails_w_multiple_groups(self): - err_msg = "Nodes can only be assigned to one node group.\n" - with mock.patch("sys.stderr") as m_stderr: - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'nodegroup', '--assign', '--node', - '1', '--group', '2,3']) - - msg = m_stderr.write.call_args[0][0] - self.assertEqual(msg, err_msg) - - @mock.patch('fuelclient.objects.nodegroup.NodeGroup.assign') - def test_assign_nodegroup(self, m_assign): - self.execute(['fuel', 'nodegroup', '--assign', '--node', '1', - '--group', '2']) - m_assign.assert_called_with([1]) - - self.execute(['fuel', 'nodegroup', '--assign', '--node', '1,2,3', - '--group', '2']) - m_assign.assert_called_with([1, 2, 3]) - - def test_node_group_assign_arguments_required(self): - err_msg = '"--node" and "--group" required!\n' - - node_not_present_cmd = ['fuel', 'nodegroup', '--assign', - '--group', '1'] - group_not_present_cmd = ['fuel', 'nodegroup', '--assign', - '--node', '1'] - - commands = (node_not_present_cmd, group_not_present_cmd) - - self._check_required_message_for_commands(err_msg, commands) diff --git a/fuelclient/tests/unit/v1/test_nodes.py b/fuelclient/tests/unit/v1/test_nodes.py deleted file mode 100644 index f798d6b2..00000000 --- a/fuelclient/tests/unit/v1/test_nodes.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 mock -import yaml - -from fuelclient.cli.actions import node -from fuelclient.cli import error -from fuelclient.cli import serializers -from fuelclient.tests.unit.v1 import base - -NODE_ATTRIBUTES_DATA = { - 'test_attribute': 'value' -} - - -class TestNodeSetAction(base.UnitTestCase): - - def setUp(self): - super(TestNodeSetAction, self).setUp() - self.node_action = node.NodeAction() - self.node_id = 1 - self.params = mock.Mock() - self.params.node = [self.node_id] - - def test_more_than_one_node(self): - mput = self.m_request.put('/api/v1/nodes/{0}/'.format(self.node_id)) - self.params.hostname = 'whatever' - self.params.name = 'whatever2' - self.params.node = [1, 2] - - error_msg = r"You should select only one node to change\." - with self.assertRaisesRegexp(error.ArgumentException, error_msg): - self.node_action.set_hostname(self.params) - - with self.assertRaisesRegexp(error.ArgumentException, error_msg): - self.node_action.set_name(self.params) - - self.assertFalse(mput.called) - - def test_set_name(self): - test_cases = ('new-name', 'New Name', u'śćż∑ Pó', u'测试 测试') - for name in test_cases: - self.params.name = name - mput = self.m_request.put( - '/api/v1/nodes/{0}/'.format(self.node_id), - json={}) - with mock.patch.object(self.node_action.serializer, - 'print_to_output') as mprint: - self.node_action.set_name(self.params) - - self.assertEqual(mput.call_count, 1) - self.assertEqual({'name': name}, mput.last_request.json()) - mprint.assert_called_once_with( - {}, - u"Name for node with id {0} has been changed to {1}.".format( - self.node_id, name) - ) - - def test_set_hostname(self): - new_hostname = 'new_hostname' - self.params.hostname = new_hostname - - mput = self.m_request.put( - '/api/v1/nodes/{0}/'.format(self.node_id), - json={}) - - with mock.patch.object(self.node_action.serializer, - 'print_to_output') as mprint: - self.node_action.set_hostname(self.params) - - self.assertEqual(mput.call_count, 1) - self.assertEqual({'hostname': new_hostname}, mput.last_request.json()) - mprint.assert_called_once_with( - {}, - "Hostname for node with id {0} has been changed to {1}.".format( - self.node_id, new_hostname) - ) - - -class TestNodeActions(base.UnitTestCase): - def setUp(self): - super(TestNodeActions, self).setUp() - self.node_id = 1 - - @mock.patch('fuelclient.objects.node.os.mkdir', mock.Mock()) - def test_attributes_download(self): - mget = self.m_request.get( - '/api/v1/nodes/{0}/attributes/'.format(self.node_id), - json=NODE_ATTRIBUTES_DATA) - - cmd = ['fuel', 'node', '--node', '1', '--attributes', - '--dir', '/fake/dir/', '--download'] - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', m_open, - create=True): - self.execute(cmd) - - self.assertTrue(mget.called) - m_open.assert_called_once_with( - '/fake/dir/node_{0}/attributes.yaml'.format(self.node_id), - mock.ANY) - serializer = serializers.Serializer() - m_open().write.assert_called_once_with( - serializer.serialize(NODE_ATTRIBUTES_DATA)) - - @mock.patch('fuelclient.objects.node.os.path.exists', - mock.Mock(return_value=True)) - def test_attributes_upload(self): - mput = self.m_request.put( - '/api/v1/nodes/{0}/attributes/'.format(self.node_id), - json=NODE_ATTRIBUTES_DATA) - - cmd = ['fuel', 'node', '--node', '1', '--attributes', - '--dir', '/fake/dir', '--upload'] - m_open = mock.mock_open(read_data=yaml.safe_dump(NODE_ATTRIBUTES_DATA)) - with mock.patch('fuelclient.cli.serializers.open', m_open, - create=True): - self.execute(cmd) - - self.assertTrue(mput.called) - m_open.assert_called_once_with( - '/fake/dir/node_{0}/attributes.yaml'.format(self.node_id), - mock.ANY) - self.assertEqual(mput.last_request.json(), NODE_ATTRIBUTES_DATA) - m_open().read.assert_called_once_with() diff --git a/fuelclient/tests/unit/v1/test_nodes_execute_tasks.py b/fuelclient/tests/unit/v1/test_nodes_execute_tasks.py deleted file mode 100644 index 160d8539..00000000 --- a/fuelclient/tests/unit/v1/test_nodes_execute_tasks.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - -from mock import patch -import requests_mock as rm - -from fuelclient.tests.unit.v1 import base -from fuelclient.tests.utils import fake_node - - -class TestNodeExecuteTasksAction(base.UnitTestCase): - - def setUp(self): - super(TestNodeExecuteTasksAction, self).setUp() - self.tasks = ['netconfig', 'hiera', 'install'] - - node_patch = patch('fuelclient.objects.node.Node.get_fresh_data') - m_fresh_data = node_patch.start() - m_fresh_data.return_value = fake_node.get_fake_node() - self.addCleanup(node_patch.stop) - - def test_execute_provided_list_of_tasks(self): - put = self.m_request.put(rm.ANY, json={'id': 43}) - - self.execute(['fuel', 'node', '--node', '1,2', '--tasks'] + self.tasks) - self.assertEqual( - put.last_request.path_url, - '/api/v1/clusters/1/deploy_tasks/?nodes=1,2' - ) - self.assertEqual(put.last_request.json(), self.tasks) - - def test_execute_provided_list_of_tasks_w_force(self): - put = self.m_request.put(rm.ANY, json={'id': 43}) - - self.execute((['fuel', 'node', '--node', '1,2', '--tasks'] - + self.tasks + ['--force'])) - self.assertEqual( - put.last_request.path_url, - '/api/v1/clusters/1/deploy_tasks/?nodes=1,2&force=1' - ) - self.assertEqual(put.last_request.json(), self.tasks) - - def test_execute_provided_list_of_tasks_noop_run(self): - put = self.m_request.put(rm.ANY, json={'id': 43}) - - self.execute((['fuel', 'node', '--node', '1,2', '--tasks'] - + self.tasks + ['--noop'])) - self.assertEqual( - put.last_request.url, - 'http://127.0.0.1:8000/api/v1/clusters/1/deploy_tasks/?nodes=1,2' - '&noop_run=1') - self.assertEqual(put.last_request.json(), self.tasks) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_skipped_tasks(self, get_tasks): - get_tasks.return_value = [{'id': t} for t in self.tasks] - put = self.m_request.put(rm.ANY, json={'id': 43}) - - self.execute( - ['fuel', 'node', '--node', '1,2', '--skip'] + self.tasks[:2]) - - self.assertEqual(put.last_request.json(), self.tasks[2:]) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_included_tasks(self, get_tasks): - get_tasks.return_value = [{'id': t} for t in self.tasks] - put = self.m_request.put(rm.ANY, json={'id': 43}) - - self.execute( - ['fuel', 'node', '--node', '1', '--start', 'netconfig', - '--tasks', 'hiera']) - self.assertEqual(put.last_request.json(), self.tasks) - get_tasks.assert_called_once_with( - start='netconfig', end=None, include=['hiera']) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_dont_fail_on_empty_tasks(self, get_tasks): - get_tasks.return_value = [] - self.execute( - ['fuel', 'node', '--node', '1', '--start', 'netconfig']) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_end_param(self, get_tasks): - put = self.m_request.put(rm.ANY, json={'id': 43}) - - get_tasks.return_value = [{'id': t} for t in self.tasks[:2]] - self.execute( - ['fuel', 'node', '--node', '1,2', '--end', self.tasks[-2]]) - self.assertEqual(put.last_request.json(), self.tasks[:2]) - get_tasks.assert_called_once_with( - end=self.tasks[-2], start=None, include=None) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_skip_with_end_param(self, get_tasks): - get_tasks.return_value = [{'id': t} for t in self.tasks] - put = self.m_request.put(rm.ANY, json={'id': 43}) - self.execute( - ['fuel', 'node', '--node', '1,2', - '--end', self.tasks[-1], '--skip'] + self.tasks[:2]) - - self.assertEqual(put.last_request.json(), self.tasks[2:]) - get_tasks.assert_called_once_with( - end=self.tasks[-1], start=None, include=None) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_start_with_end_param(self, get_tasks): - """end will be included.""" - put = self.m_request.put(rm.ANY, json={'id': 43}) - start = 1 - end = 2 - get_tasks.return_value = [{'id': t} for t in self.tasks[start:end + 1]] - self.execute( - ['fuel', 'node', '--node', '1,2', '--start', self.tasks[start], - '--end', self.tasks[end]]) - - self.assertEqual(put.last_request.json(), self.tasks[start:end + 1]) - get_tasks.assert_called_once_with( - end=self.tasks[2], start=self.tasks[1], include=None) - - @patch('fuelclient.objects.environment.Environment.get_deployment_tasks') - def test_start_param(self, get_tasks): - put = self.m_request.put(rm.ANY, json={'id': 43}) - get_tasks.return_value = [{'id': t} for t in self.tasks[1:]] - self.execute( - ['fuel', 'node', '--node', '1,2', '--start', self.tasks[1]]) - - self.assertEqual(put.last_request.json(), self.tasks[1:]) - get_tasks.assert_called_once_with( - start=self.tasks[1], end=None, include=None) diff --git a/fuelclient/tests/unit/v1/test_nodes_general_action.py b/fuelclient/tests/unit/v1/test_nodes_general_action.py deleted file mode 100644 index 4d83a51e..00000000 --- a/fuelclient/tests/unit/v1/test_nodes_general_action.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 mock -from six import StringIO - -from fuelclient.cli.actions import node -from fuelclient.tests.unit.v1 import base - - -GRAPH_API_OUTPUT = "digraph G { A -> B -> C }" -TASKS_API_OUTPUT = [ - {'id': 'primary-controller'}, - {'id': 'sync-time'}, -] - - -class TestNodeStartAction(base.UnitTestCase): - - @mock.patch.object(node.NodeAction, 'get_env_id', return_value=None) - def test_node_not_assigend(self, _): - for method in ('--deploy', '--provision'): - with mock.patch('sys.stderr', new=StringIO()) as mstderr: - self.assertRaises(SystemExit, - self.execute, - ['fuel', 'node', method, '--node', '8']) - self.assertIn( - "Input nodes are not assigned to any environment!", - mstderr.getvalue()) diff --git a/fuelclient/tests/unit/v1/test_notifications_action.py b/fuelclient/tests/unit/v1/test_notifications_action.py deleted file mode 100644 index 93e3bb41..00000000 --- a/fuelclient/tests/unit/v1/test_notifications_action.py +++ /dev/null @@ -1,211 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - -from mock import patch -import requests_mock as rm - -from fuelclient.tests.unit.v1 import base - - -class TestNotificationsActions(base.UnitTestCase): - def test_notification_send(self): - post = self.m_request.post(rm.ANY, json={}) - - self.execute( - ['fuel', 'notifications', '--send', 'test message']) - self.assertEqual(post.call_count, 1) - - request = post.last_request.json() - self.assertEqual('test message', request['message']) - self.assertEqual('done', request['topic']) - - self.execute( - ['fuel', 'notify', '-m', 'test message 2']) - self.assertEqual(post.call_count, 2) - - request = post.last_request.json() - self.assertEqual('test message 2', request['message']) - self.assertEqual('done', request['topic']) - - def test_notification_send_with_topic(self): - post = self.m_request.post(rm.ANY, json={}) - - self.execute( - ['fuel', 'notifications', '--send', 'test error', - '--topic', 'error']) - self.assertEqual(post.call_count, 1) - request = post.last_request.json() - self.assertEqual('test error', request['message']) - self.assertEqual('error', request['topic']) - - self.execute( - ['fuel', 'notify', '-m', 'test error 2', '--topic', 'error']) - self.assertEqual(post.call_count, 2) - request = post.last_request.json() - self.assertEqual('test error 2', request['message']) - self.assertEqual('error', request['topic']) - - def test_notification_send_no_message(self): - post = self.m_request.post(rm.ANY, json={}) - - self.assertRaises( - SystemExit, - self.execute, - ['fuel', 'notifications', '--send'] - ) - self.assertFalse(post.called) - - self.assertRaises( - SystemExit, - self.execute, - ['fuel', 'notify', '-m'] - ) - self.assertFalse(post.called) - - def test_notification_send_invalid_topic(self): - post = self.m_request.post(rm.ANY, json={}) - - self.assertRaises( - SystemExit, - self.execute, - ['fuel', 'notifications', '--send', 'test message', - '--topic', 'x'] - ) - self.assertFalse(post.called) - - self.assertRaises( - SystemExit, - self.execute, - ['fuel', 'notify', '-m', 'test message', '--topic', 'x'] - ) - self.assertFalse(post.called) - - def test_mark_as_read(self): - results = [{'id': 1, - 'message': 'test message', - 'status': 'unread', - 'topic': 'done'}, - {'id': 2, - 'message': 'test message 2', - 'status': 'unread', - 'topic': 'done'}] - results.extend(results) - - get = self.m_request.get(rm.ANY, [{'json': r} for r in results]) - put = self.m_request.put(rm.ANY, json={}) - - self.execute( - ['fuel', 'notifications', '-r', '1']) - - self.assertEqual(get.call_count, 1) - self.assertEqual(put.call_count, 1) - - messages = put.last_request.json() - self.assertEqual(1, len(messages)) - - msg = messages.pop() - self.assertEqual('test message', msg['message']) - self.assertEqual('read', msg['status']) - self.assertEqual(1, msg['id']) - - self.execute( - ['fuel', 'notifications', '-r', '1', '2']) - - self.assertEqual(get.call_count, 3) - self.assertEqual(put.call_count, 2) - - messages = put.last_request.json() - self.assertEqual(2, len(messages)) - - msg = messages.pop() - self.assertEqual('test message', msg['message']) - self.assertEqual('read', msg['status']) - self.assertEqual(1, msg['id']) - - msg = messages.pop() - self.assertEqual('test message 2', msg['message']) - self.assertEqual('read', msg['status']) - self.assertEqual(2, msg['id']) - - def test_mark_all_as_read(self): - result = [{'id': 1, - 'message': 'test message', - 'status': 'unread', - 'topic': 'done'}, - {'id': 2, - 'message': 'test message 2', - 'status': 'unread', - 'topic': 'done'}] - - get = self.m_request.get(rm.ANY, json=result) - put = self.m_request.put(rm.ANY, json={}) - - self.execute( - ['fuel', 'notifications', '-r', '*']) - - self.assertEqual(get.call_count, 1) - self.assertEqual(put.call_count, 1) - request = put.last_request.json() - self.assertEqual('test message', request[0]['message']) - self.assertEqual('read', request[0]['status']) - self.assertEqual('test message 2', request[1]['message']) - self.assertEqual('read', request[1]['status']) - - @patch('fuelclient.cli.actions.notifications.format_table') - def test_list_notifications(self, mformat_table): - test_notifications = [{'id': 1, - 'message': 'test message', - 'status': 'unread', - 'topic': 'done'}, - {'id': 2, - 'message': 'test message 2', - 'status': 'read', - 'topic': 'done'}] - get = self.m_request.get(rm.ANY, json=test_notifications) - self.m_request.put(rm.ANY, json={}) - - self.execute(['fuel', 'notifications']) - - self.assertEqual(get.call_count, 1) - notifications = mformat_table.call_args[0][0] - self.assertEqual(len(notifications), 1) - self.assertDictEqual(notifications[0], test_notifications[0]) - - @patch('fuelclient.cli.actions.notifications.format_table') - def test_list_all_notifications(self, mformat_table): - test_notifications = [ - { - 'id': 1, - 'message': 'test message', - 'status': 'unread', - 'topic': 'done', - }, - { - 'id': 2, - 'message': 'test message 2', - 'status': 'read', - 'topic': 'done', - } - ] - get = self.m_request.get(rm.ANY, json=test_notifications) - self.m_request.put(rm.ANY, json={}) - - self.execute(['fuel', 'notifications', '-a']) - - self.assertEqual(get.call_count, 1) - notifications = mformat_table.call_args[0][0] - self.assertEqual(len(notifications), 2) - self.assertListEqual(notifications, test_notifications) diff --git a/fuelclient/tests/unit/v1/test_openstack_config.py b/fuelclient/tests/unit/v1/test_openstack_config.py deleted file mode 100644 index 5ad52528..00000000 --- a/fuelclient/tests/unit/v1/test_openstack_config.py +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright 2015 Mirantis, 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 json -import mock -import yaml - -from fuelclient.tests.unit.v1 import base -from fuelclient.tests import utils - - -class TestOpenstackConfigActions(base.UnitTestCase): - - def setUp(self): - super(TestOpenstackConfigActions, self).setUp() - - self.config = utils.get_fake_openstack_config() - - def test_config_download(self): - m_get = self.m_request.get( - '/api/v1/openstack-config/42/', json=self.config) - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.execute(['fuel', 'openstack-config', - '--config-id', '42', '--download', - '--file', 'config.yaml']) - - self.assertTrue(m_get.called) - content = m_open().write.mock_calls[0][1][0] - content = yaml.safe_load(content) - self.assertEqual(self.config['configuration'], - content['configuration']) - - @mock.patch('sys.stderr') - def test_config_download_fail(self, mocked_stderr): - self.assertRaises( - SystemExit, - self.execute, ['fuel', 'openstack-config', '--download', - '--config-id', '1']) - mocked_stderr.write.assert_called_once_with( - '"--config-id" and "--file" required!\n') - mocked_stderr.reset_mock() - - self.assertRaises( - SystemExit, - self.execute, ['fuel', 'openstack-config', '--download', - '--file', 'config.yaml']) - mocked_stderr.write.assert_called_once_with( - '"--config-id" and "--file" required!\n') - - def test_config_upload(self): - m_post = self.m_request.post( - '/api/v1/openstack-config/', json=[self.config]) - m_open = mock.mock_open(read_data=yaml.safe_dump( - {'configuration': self.config['configuration']})) - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - with mock.patch('fuelclient.objects.openstack_config.os'): - self.execute(['fuel', 'openstack-config', '--env', '1', - '--upload', '--file', 'config.yaml']) - self.assertTrue(m_post.called) - - req = json.loads(m_post.last_request.text) - self.assertEqual(req['cluster_id'], 1) - - def test_config_upload_multinode(self): - configs = [utils.get_fake_openstack_config(node_id=node_id) - for node_id in [1, 2, 3]] - - m_post = self.m_request.post( - '/api/v1/openstack-config/', json=configs) - - m_open = mock.mock_open(read_data=yaml.safe_dump( - {'configuration': self.config['configuration']})) - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - with mock.patch('fuelclient.objects.openstack_config.os'): - self.execute(['fuel', 'openstack-config', '--env', '1', - '--node', '1,2,3', - '--upload', '--file', 'config.yaml']) - self.assertTrue(m_post.called) - - req = json.loads(m_post.last_request.text) - self.assertEqual(req['node_ids'], [1, 2, 3]) - self.assertEqual(req['cluster_id'], 1) - - @mock.patch('sys.stderr') - def test_config_upload_fail(self, mocked_stderr): - self.assertRaises( - SystemExit, - self.execute, ['fuel', 'openstack-config', '--env', '1', - '--upload']) - mocked_stderr.write.assert_called_once_with( - '"--env" and "--file" required!\n') - mocked_stderr.reset_mock() - - self.assertRaises( - SystemExit, - self.execute, ['fuel', 'openstack-config', '--upload', - '--file', 'config.yaml']) - mocked_stderr.write.assert_called_once_with( - '"--env" and "--file" required!\n') - - def test_config_list(self): - m_get = self.m_request.get( - '/api/v1/openstack-config/?cluster_id=84', json=[ - utils.get_fake_openstack_config(id=1, cluster_id=32), - utils.get_fake_openstack_config(id=2, cluster_id=64) - ]) - self.execute(['fuel', 'openstack-config', '--env', '84', '--list']) - self.assertTrue(m_get.called) - - def test_config_list_w_filters(self): - m_get = self.m_request.get( - '/api/v1/openstack-config/?cluster_id=84&node_role=controller', - json=[utils.get_fake_openstack_config(id=1, cluster_id=32)]) - self.execute(['fuel', 'openstack-config', '--env', '84', - '--role', 'controller', '--list']) - self.assertTrue(m_get.called) - - m_get = self.m_request.get( - '/api/v1/openstack-config/?cluster_id=84&node_ids=42', json=[ - utils.get_fake_openstack_config(id=1, cluster_id=32), - ]) - self.execute(['fuel', 'openstack-config', '--env', '84', - '--node', '42', '--list']) - self.assertTrue(m_get.called) - - def test_config_list_multinode(self): - m_get = self.m_request.get( - '/api/v1/openstack-config/?cluster_id=84&node_ids=1,2,3', - json=[utils.get_fake_openstack_config( - id=1, cluster_id=32, node_id=1)]) - - self.execute(['fuel', 'openstack-config', '--env', '84', - '--node', '1,2,3', '--list']) - self.assertTrue(m_get.called) - - @mock.patch('sys.stderr') - def test_config_list_fail(self, m_stderr): - self.assertRaises( - SystemExit, - self.execute, ['fuel', 'openstack-config', '--list']) - m_stderr.write.assert_called_once_with( - '"--env" required!\n') - - def test_config_delete(self): - m_del = self.m_request.delete( - '/api/v1/openstack-config/42/', json={}) - self.execute(['fuel', 'openstack-config', - '--config-id', '42', '--delete']) - self.assertTrue(m_del.called) - - def test_config_execute(self): - m_put = self.m_request.put('/api/v1/openstack-config/execute/', - json={'status': 'ready'}) - self.execute(['fuel', 'openstack-config', '--env', '42', '--execute']) - self.assertTrue(m_put.called) - self.assertEqual({"cluster_id": 42, "force": False}, - json.loads(m_put.last_request.text)) - - def test_config_execute_multinode(self): - m_put = self.m_request.put('/api/v1/openstack-config/execute/', - json={'status': 'ready'}) - - self.execute(['fuel', 'openstack-config', '--env', '42', - '--node', '1,2,3', '--execute']) - self.assertTrue(m_put.called) - self.assertEqual( - {"cluster_id": 42, "force": False, "node_ids": [1, 2, 3]}, - json.loads(m_put.last_request.text)) - - def test_config_force_execute(self): - m_put = self.m_request.put('/api/v1/openstack-config/execute/', - json={'status': 'ready'}) - self.execute(['fuel', 'openstack-config', '--env', '42', '--execute', - '--force']) - self.assertTrue(m_put.called) - self.assertEqual({"cluster_id": 42, "force": True}, - json.loads(m_put.last_request.text)) - - def test_config_execute_fail(self): - message = 'Some error' - m_put = self.m_request.put( - '/api/v1/openstack-config/execute/', - json={'status': 'error', 'message': message}) - - with mock.patch("sys.stdout") as m_stdout: - self.execute(['fuel', 'openstack-config', - '--env', '42', '--execute']) - self.assertTrue(m_put.called) - self.assertIn(message, m_stdout.write.call_args_list[0][0][0]) diff --git a/fuelclient/tests/unit/v1/test_parser.py b/fuelclient/tests/unit/v1/test_parser.py deleted file mode 100644 index 8843136b..00000000 --- a/fuelclient/tests/unit/v1/test_parser.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 mock - -from fuelclient.tests.unit.v1 import base - - -class TestParser(base.UnitTestCase): - - def test_choose_only_one_format(self): - with mock.patch('sys.stderr') as mstderr: - self.assertRaises(SystemExit, - self.execute, - ['fuel', '--json', '--yaml']) - args, _ = mstderr.write.call_args - self.assertRegexpMatches( - args[0], - r"argument (--json|--yaml): not allowed with" - r" argument (--yaml|--json)") diff --git a/fuelclient/tests/unit/v1/test_performance.py b/fuelclient/tests/unit/v1/test_performance.py deleted file mode 100644 index 7509ff7f..00000000 --- a/fuelclient/tests/unit/v1/test_performance.py +++ /dev/null @@ -1,153 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 json -import os -import shutil -import tarfile -import time - -import mock -import requests_mock as rm -from six import moves as six_moves -import testtools - -from fuelclient import client -from fuelclient import fuelclient_settings -from fuelclient import profiler -from fuelclient.tests.unit.v1 import base -from fuelclient.tests import utils - - -@testtools.skipUnless(profiler.profiling_enabled(), - 'Performance profiling tests are not ' - 'enabled in settings.yaml.') -class ClientPerfTest(base.UnitTestCase): - - NUMBER_OF_NODES = 100 - - @classmethod - def setUpClass(cls): - super(ClientPerfTest, cls).setUpClass() - - cls.nodes = cls.get_random_nodes(cls.NUMBER_OF_NODES) - settings = fuelclient_settings.get_settings() - test_base = settings.PERF_TESTS_PATHS['perf_tests_base'] - - if os.path.exists(test_base): - shutil.rmtree(test_base) - - os.makedirs(test_base) - - @classmethod - def tearDownClass(cls): - """Packs all the files from the profiling.""" - - settings = fuelclient_settings.get_settings() - test_base = settings.PERF_TESTS_PATHS['perf_tests_base'] - test_results = settings.PERF_TESTS_PATHS['perf_tests_results'] - - if not os.path.exists(test_results): - os.makedirs(test_results) - - if os.path.exists(test_base): - test_result_name = os.path.join( - test_results, - '{name:s}_{timestamp}.tar.gz'.format(name=cls.__name__, - timestamp=time.time())) - tar = tarfile.open(test_result_name, "w:gz") - tar.add(test_base) - tar.close() - - shutil.rmtree(test_base) - - def setUp(self): - super(ClientPerfTest, self).setUp() - - token_patcher = mock.patch.object(client.APIClient, 'auth_token', - new_callable=mock.PropertyMock) - self.mock_auth_token = token_patcher.start() - self.addCleanup(self.mock_auth_token.stop) - - @classmethod - def get_random_nodes(cls, number): - """Returns specified number of random fake nodes.""" - - return [utils.get_fake_node() for i in six_moves.range(number)] - - def _invoke_client(self, *args): - """Invokes Fuel Client with the specified arguments.""" - - args = ['fuelclient'] + list(args) - self.execute(args) - - def mock_nailgun_response(self, *responses): - """Mocks network requests in order to return specified content.""" - - m_responses = [] - - for resp in responses: - m_resp = {'text': resp, 'status': 200} - - m_responses.append(m_resp) - - self.m_request.stop() - self.m_request = rm.Mocker() - self.top_matcher = self.m_request.register_uri(rm.ANY, - rm.ANY, - m_responses) - - self.addCleanup(self.m_request.stop) - - def test_list_nodes(self): - nodes_text = json.dumps(self.nodes) - self.mock_nailgun_response(nodes_text) - - self._invoke_client('node', 'list') - - def test_assign_nodes(self): - node_ids = ','.join([str(n['id']) for n in self.nodes]) - - self.mock_nailgun_response('{}') - self._invoke_client('--env', '42', 'node', 'set', '--node', - node_ids, '--role', 'compute') - - def test_list_environment(self): - # NOTE(romcheg): After 100 nodes were added to an environment - # they are listed as pending changes so that may potentially - # affect the performance. - env = [utils.get_fake_env()] - resp_text = json.dumps(env) - - self.mock_nailgun_response(resp_text) - - self._invoke_client('env', '--list') - - @mock.patch('__builtin__.open', create=True) - def test_upload_node_settings(self, m_open): - node_configs = [json.dumps(utils.get_fake_network_config(3)) - for i in six_moves.range(self.NUMBER_OF_NODES)] - - node_ids = ','.join([str(n['id']) for n in self.nodes]) - - m_open.return_value = mock.MagicMock(spec=file) - m_file = m_open.return_value.__enter__.return_value - m_file.read.side_effect = node_configs - - self.mock_nailgun_response(*node_configs) - - self._invoke_client('--json', 'node', '--node-id', node_ids, - '--network', '--upload', '--dir', '/fake/dir') diff --git a/fuelclient/tests/unit/v1/test_plugins_action.py b/fuelclient/tests/unit/v1/test_plugins_action.py deleted file mode 100644 index 4c1166ab..00000000 --- a/fuelclient/tests/unit/v1/test_plugins_action.py +++ /dev/null @@ -1,209 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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. - -from mock import patch - -from fuelclient.cli.actions import PluginAction -from fuelclient.cli import error -from fuelclient.cli.formatting import format_table -from fuelclient.cli.serializers import Serializer -from fuelclient.objects.plugins import Plugins -from fuelclient.tests.unit.v1 import base - - -class TestPluginsActions(base.UnitTestCase): - - def setUp(self): - super(TestPluginsActions, self).setUp() - self.file_name = '/tmp/path/plugin.fp' - self.attr_name = 'plugin_name==version' - self.name = 'plugin_name' - self.version = 'version' - - def exec_plugins(self, actions): - plugins_cmd = ['fuel', 'plugins'] - plugins_cmd.extend(actions) - self.execute(plugins_cmd) - - def assert_print_table(self, print_mock, plugins): - print_mock.assert_called_once_with( - plugins, format_table( - plugins, - acceptable_keys=PluginAction.acceptable_keys)) - - def assert_print(self, print_mock, result, msg): - print_mock.assert_called_once_with(result, msg) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'get_all_data') - def test_list_default(self, get_mock, print_mock): - plugins = [ - {'id': 1, - 'name': 'plugin_name1', - 'version': '1.0.0', - 'package_version': '1.0.0', - 'releases': [{'os': 'ubuntu', 'version': 'liberty-8.0'}, - {'os': 'centos', 'version': 'liberty-8.0'}]}, - {'id': 2, - 'name': 'plugin_name2', - 'version': '1.0.0', - 'package_version': '1.0.0', - 'releases': [{'os': 'ubuntu', 'version': 'liberty-8.0'}, - {'os': 'ubuntu', 'version': 'mitaka-9.0'}]} - ] - get_mock.return_value = plugins - - self.exec_plugins([]) - - get_mock.assert_called_once_with() - self.assert_print_table(print_mock, plugins) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'get_all_data') - def test_list(self, get_mock, print_mock): - plugins = [ - {'id': 1, - 'name': 'plugin_name1', - 'version': '1.0.0', - 'package_version': '1.0.0', - 'releases': [{'os': 'ubuntu', 'version': 'liberty-8.0'}, - {'os': 'centos', 'version': 'liberty-8.0'}]}, - {'id': 2, - 'name': 'plugin_name2', - 'version': '1.0.0', - 'package_version': '1.0.0', - 'releases': [{'os': 'ubuntu', 'version': 'liberty-8.0'}, - {'os': 'ubuntu', 'version': 'mitaka-9.0'}]} - ] - get_mock.return_value = plugins - - self.exec_plugins(['--list']) - - get_mock.assert_called_once_with() - self.assert_print_table(print_mock, plugins) - - @patch.object(Serializer, 'print_to_output') - @patch.object(PluginAction, 'check_file') - @patch.object(Plugins, 'install', return_value='some_result') - def test_install(self, install_mock, check_mock, print_mock): - self.exec_plugins(['--install', self.file_name]) - self.assert_print( - print_mock, - 'some_result', - 'Plugin /tmp/path/plugin.fp was successfully installed.') - install_mock.assert_called_once_with(self.file_name, force=False) - check_mock.assert_called_once_with(self.file_name) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'remove', return_value='some_result') - def test_remove(self, remove_mock, print_mock): - self.exec_plugins(['--remove', self.attr_name]) - self.assert_print( - print_mock, - 'some_result', - 'Plugin plugin_name==version was successfully removed.') - remove_mock.assert_called_once_with(self.name, self.version) - - @patch.object(Serializer, 'print_to_output') - @patch.object(PluginAction, 'check_file') - @patch.object(Plugins, 'update', return_value='some_result') - def test_update(self, update_mock, check_mock, print_mock): - self.exec_plugins(['--update', self.file_name]) - self.assert_print( - print_mock, - 'some_result', - 'Plugin /tmp/path/plugin.fp was successfully updated.') - update_mock.assert_called_once_with(self.file_name) - check_mock.assert_called_once_with(self.file_name) - - @patch.object(Serializer, 'print_to_output') - @patch.object(PluginAction, 'check_file') - @patch.object(Plugins, 'downgrade', return_value='some_result') - def test_downgrade(self, downgrade_mock, check_mock, print_mock): - self.exec_plugins(['--downgrade', self.file_name]) - self.assert_print( - print_mock, - 'some_result', - 'Plugin /tmp/path/plugin.fp was successfully downgraded.') - downgrade_mock.assert_called_once_with(self.file_name) - check_mock.assert_called_once_with(self.file_name) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'sync') - def test_sync(self, sync_mock, print_mock): - self.exec_plugins(['--sync']) - self.assert_print( - print_mock, - None, - 'Plugins were successfully synchronized.') - self.assertTrue(sync_mock.called) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'sync') - def test_sync_with_specific_plugins(self, sync_mock, print_mock): - self.exec_plugins(['--sync', '--plugin-id=1,2,3']) - self.assert_print( - print_mock, - None, - 'Plugins were successfully synchronized.') - sync_mock.assert_called_once_with(plugin_ids=[1, 2, 3]) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'register', return_value='some_result') - def test_register(self, register_mock, print_mock): - self.exec_plugins(['--register', 'plugin_name==version']) - self.assert_print( - print_mock, - 'some_result', - 'Plugin plugin_name==version was successfully registered.') - register_mock.assert_called_once_with( - self.name, self.version, force=False) - - @patch.object(Serializer, 'print_to_output') - @patch.object(Plugins, 'unregister', return_value='some_result') - def test_unregister(self, unregister_mock, print_mock): - self.exec_plugins(['--unregister', 'plugin_name==version']) - self.assert_print( - print_mock, - 'some_result', - 'Plugin plugin_name==version was successfully unregistered.') - unregister_mock.assert_called_once_with(self.name, self.version) - - def test_parse_name_version(self): - plugin = PluginAction() - self.assertEqual( - plugin.parse_name_version('name==version'), - ['name', 'version']) - - def test_parse_name_version_raises_error(self): - plugin = PluginAction() - self.assertRaisesRegexp( - error.ArgumentException, - 'Syntax: fuel plugins fuel_plugin==1.0.0', - plugin.parse_name_version, 'some_string') - - @patch('fuelclient.utils.file_exists', return_value=True) - def test_check_file(self, _): - plugin = PluginAction() - plugin.check_file(self.file_name) - - @patch('fuelclient.utils.file_exists', return_value=False) - def test_check_file_raises_error(self, _): - plugin = PluginAction() - self.assertRaisesRegexp( - error.ArgumentException, - 'File "/tmp/path/plugin.fp" does not exists', - plugin.check_file, self.file_name) diff --git a/fuelclient/tests/unit/v1/test_plugins_object.py b/fuelclient/tests/unit/v1/test_plugins_object.py deleted file mode 100644 index c959b5d2..00000000 --- a/fuelclient/tests/unit/v1/test_plugins_object.py +++ /dev/null @@ -1,485 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 fixtures -import mock -from mock import MagicMock -from mock import patch - -from fuelclient.cli import error -from fuelclient.objects import plugins -from fuelclient.objects.plugins import Plugins -from fuelclient.objects.plugins import PluginV1 -from fuelclient.objects.plugins import PluginV2 -from fuelclient.tests.unit.v1 import base -from fuelclient import utils - - -@patch('fuelclient.objects.plugins.raise_error_if_not_master') -class TestPluginV1(base.UnitTestCase): - - fake_meta = """ - name: 'plugin_name' - version: 'version' - """ - - def setUp(self): - super(TestPluginV1, self).setUp() - self.plugin = PluginV1 - self.path = '/tmp/plugin/path' - self.name = 'plugin_name' - self.version = 'version' - - @patch('fuelclient.objects.plugins.tarfile') - def test_install(self, tar_mock, master_only_mock): - tar_obj = MagicMock() - tar_mock.open.return_value = tar_obj - - self.plugin.install(self.path) - - master_only_mock.assert_called_once_with() - tar_obj.extractall.assert_called_once_with('/var/www/nailgun/plugins/') - tar_obj.close.assert_called_once_with() - - @patch('fuelclient.objects.plugins.shutil.rmtree') - def test_remove(self, rmtree_mock, master_only_mock): - self.plugin.remove(self.name, self.version) - - master_only_mock.assert_called_once_with() - rmtree_mock.assert_called_once_with( - '/var/www/nailgun/plugins/plugin_name-version') - - def test_update(self, _): - self.assertRaisesRegexp( - error.BadDataException, - 'Update action is not supported for old plugins with ' - 'package version "1.0.0", you can install your plugin ' - 'or use newer plugin format.', - self.plugin.update, 'some_string') - - def test_downgrade(self, _): - self.assertRaisesRegexp( - error.BadDataException, - 'Downgrade action is not supported for old plugins with ' - 'package version "1.0.0", you can install your plugin ' - 'or use newer plugin format.', - self.plugin.downgrade, 'some_string') - - def mock_tar(self, tar_mock): - tar_obj = MagicMock() - tar_mock.open.return_value = tar_obj - tar_file = MagicMock() - tar_obj.getnames.return_value = ['metadata.yaml'] - tar_obj.extractfile.return_value = tar_file - tar_file.read.return_value = self.fake_meta - - @patch('fuelclient.objects.plugins.tarfile') - def test_name_from_file(self, tar_mock, _): - self.mock_tar(tar_mock) - - self.assertEqual( - self.plugin.name_from_file(self.path), - self.name) - - @patch('fuelclient.objects.plugins.tarfile') - def test_version_from_file(self, tar_mock, _): - self.mock_tar(tar_mock) - - self.assertEqual( - self.plugin.version_from_file(self.path), - self.version) - - -@patch('fuelclient.objects.plugins.raise_error_if_not_master') -class TestPluginV2(base.UnitTestCase): - - def setUp(self): - super(TestPluginV2, self).setUp() - self.plugin = PluginV2 - self.path = '/tmp/plugin/path' - self.name = 'plugin_name' - self.version = '1.2.3' - - @patch('fuelclient.objects.plugins.utils.exec_cmd') - def test_install(self, exec_mock, master_only_mock): - self.plugin.install(self.path) - - exec_mock.assert_called_once_with( - 'yum -y install --disablerepo=\'*\' /tmp/plugin/path') - master_only_mock.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.exec_cmd') - def test_install_w_force(self, exec_mock, master_only_mock): - self.plugin.install(self.path, force=True) - - exec_mock.assert_called_once_with( - 'yum -y install --disablerepo=\'*\' /tmp/plugin/path' - ' || yum -y reinstall --disablerepo=\'*\' /tmp/plugin/path') - master_only_mock.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.exec_cmd') - def test_remove(self, exec_mock, master_only_mock): - self.plugin.remove(self.name, self.version) - - exec_mock.assert_called_once_with('yum -y remove plugin_name-1.2') - master_only_mock.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.exec_cmd') - def test_update(self, exec_mock, master_only_mock): - self.plugin.update(self.path) - - exec_mock.assert_called_once_with('yum -y update /tmp/plugin/path') - master_only_mock.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.exec_cmd') - def test_downgrade(self, exec_mock, master_only_mock): - self.plugin.downgrade(self.path) - - exec_mock.assert_called_once_with('yum -y downgrade /tmp/plugin/path') - master_only_mock.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.exec_cmd_iterator', - return_value=['plugin_name-1.2']) - def test_name_from_file(self, exec_mock, _): - self.assertEqual( - self.plugin.name_from_file(self.path), - self.name) - - exec_mock.assert_called_once_with( - "rpm -qp --queryformat '%{name}' /tmp/plugin/path") - - @patch('fuelclient.objects.plugins.utils.exec_cmd_iterator', - return_value=['1.2.3']) - def test_version_from_file(self, exec_mock, _): - self.assertEqual( - self.plugin.version_from_file(self.path), - self.version) - - exec_mock.assert_called_once_with( - "rpm -qp --queryformat '%{version}' /tmp/plugin/path") - - -class TestPluginsObject(base.UnitTestCase): - - def setUp(self): - super(TestPluginsObject, self).setUp() - self.plugin = Plugins - self.path = '/tmp/plugin/path' - self.name = 'plugin_name' - self.version = 'version' - - def mock_make_obj_by_file(self, make_obj_by_file_mock): - plugin_obj = MagicMock() - plugin_obj.name_from_file.return_value = 'retrieved_name' - plugin_obj.version_from_file.return_value = 'retrieved_version' - make_obj_by_file_mock.return_value = plugin_obj - - return plugin_obj - - @patch('fuelclient.utils.glob_and_parse_yaml', - return_value=[ - {'name': 'name1', 'version': 'version1'}, - {'name': 'name2', 'version': 'version2'}, - {'name': 'name3', 'version': 'version3'}]) - @patch.object(Plugins, 'update_or_create') - def test_register(self, up_or_create_mock, glob_parse_mock): - self.plugin.register('name3', 'version3') - glob_parse_mock.assert_called_once_with( - '/var/www/nailgun/plugins/*/metadata.yaml') - up_or_create_mock.assert_called_once_with( - {'name': 'name3', 'version': 'version3'}, - force=False) - - @patch('fuelclient.utils.glob_and_parse_yaml', return_value=[]) - def test_register_raises_error(self, glob_parse_mock): - self.assertRaisesRegexp( - error.BadDataException, - 'Plugin name3 with version version3 does ' - 'not exist, install it and try again', - self.plugin.register, 'name3', 'version3') - - glob_parse_mock.assert_called_once_with( - '/var/www/nailgun/plugins/*/metadata.yaml') - - @patch.object(Plugins, 'get_plugin', return_value={'id': 123}) - @patch.object(Plugins.connection, 'delete_request') - def test_unregister(self, del_mock, get_mock): - self.plugin.unregister(self.name, self.version) - get_mock.assert_called_once_with(self.name, self.version) - del_mock.assert_called_once_with('plugins/123') - - @patch.object(utils, 'file_exists', return_value=True) - @patch.object(Plugins, 'register') - @patch.object(Plugins, 'make_obj_by_file') - def test_install(self, make_obj_by_file_mock, register_mock, - file_exists_mock): - plugin_obj = self.mock_make_obj_by_file(make_obj_by_file_mock) - register_mock.return_value = {'id': 1} - self.plugin.install(self.path) - - plugin_obj.install.assert_called_once_with(self.path, force=False) - register_mock.assert_called_once_with( - 'retrieved_name', 'retrieved_version', force=False) - file_exists_mock.assert_called_once_with(self.path) - - @patch.object(Plugins, 'unregister') - @patch.object(Plugins, 'make_obj_by_name') - def test_remove(self, make_obj_by_name_mock, unregister_mock): - plugin_obj = MagicMock() - make_obj_by_name_mock.return_value = plugin_obj - - self.plugin.remove(self.name, self.version) - - plugin_obj.remove.assert_called_once_with(self.name, self.version) - unregister_mock.assert_called_once_with(self.name, self.version) - - @patch.object(Plugins.connection, 'post_request') - def test_sync(self, post_mock): - self.plugin.sync() - post_mock.assert_called_once_with( - api='plugins/sync/', data=None) - - @patch.object(Plugins.connection, 'post_request') - def test_sync_with_specific_plugins(self, post_mock): - self.plugin.sync(plugin_ids=[1, 2]) - data = {'ids': [1, 2]} - post_mock.assert_called_once_with( - api='plugins/sync/', data=data) - - @patch.object(Plugins, 'register') - @patch.object(Plugins, 'make_obj_by_file') - def test_update(self, make_obj_by_file_mock, register_mock): - plugin_obj = self.mock_make_obj_by_file(make_obj_by_file_mock) - - self.plugin.update(self.path) - - plugin_obj.update.assert_called_once_with(self.path) - register_mock.assert_called_once_with( - 'retrieved_name', 'retrieved_version') - - @patch.object(Plugins, 'register') - @patch.object(Plugins, 'make_obj_by_file') - def test_downgrade(self, make_obj_by_file_mock, register_mock): - plugin_obj = self.mock_make_obj_by_file(make_obj_by_file_mock) - - self.plugin.downgrade(self.path) - - plugin_obj.downgrade.assert_called_once_with(self.path) - register_mock.assert_called_once_with( - 'retrieved_name', 'retrieved_version') - - @patch.object(Plugins, 'get_plugin') - def test_make_obj_by_name_v1(self, get_mock): - plugins = [{'package_version': '1.0.0'}, - {'package_version': '1.0.1'}, - {'package_version': '1.99.99'}] - - for plugin in plugins: - get_mock.return_value = plugin - self.assertEqual( - self.plugin.make_obj_by_name(self.name, self.version), - PluginV1) - - @patch.object(Plugins, 'get_plugin') - def test_make_obj_by_name_v2(self, get_mock): - plugins = [{'package_version': '2.0.0'}, - {'package_version': '2.0.1'}, - {'package_version': '3.0.0'}] - - for plugin in plugins: - get_mock.return_value = plugin - self.assertEqual( - self.plugin.make_obj_by_name(self.name, self.version), - PluginV2) - - @patch.object(Plugins, 'get_plugin') - def test_make_obj_by_name_v2_raises_error(self, get_mock): - get_mock.return_value = {'package_version': '0.0.1'} - - self.assertRaisesRegexp( - error.BadDataException, - 'Plugin plugin_name==version has ' - 'unsupported package version 0.0.1', - self.plugin.make_obj_by_name, self.name, self.version) - - def test_make_obj_by_file_v1(self): - self.assertEqual( - self.plugin.make_obj_by_file('file-name-1.2.3.fp'), - PluginV1) - - def test_make_obj_by_file_v2(self): - self.assertEqual( - self.plugin.make_obj_by_file('file-name-1.2-1.2.3-0.noarch.rpm'), - PluginV2) - - def test_make_obj_by_file_raises_error(self): - self.assertRaisesRegexp( - error.BadDataException, - 'Plugin file-name.ext has unsupported format .ext', - self.plugin.make_obj_by_file, 'file-name.ext') - - @patch.object(Plugins, 'get_plugin_for_update', return_value={'id': 99}) - @patch.object(Plugins.connection, 'put_request', return_value={'id': 99}) - def test_update_or_create_updates(self, put_mock, get_for_update_mock): - meta = {'id': 99, 'version': '1.0.0', 'package_version': '2.0.0'} - self.plugin.update_or_create(meta) - put_mock.assert_called_once_with('plugins/99', meta) - - @patch.object(Plugins, 'get_plugin_for_update', return_value=None) - @patch.object(Plugins.connection, 'post_request_raw', - return_value=MagicMock(status_code=201)) - @patch.object(Plugins.connection, 'put_request') - def test_update_or_create_creates( - self, put_mock, post_mock, get_for_update_mock): - meta = {'id': 99, 'version': '1.0.0', 'package_version': '2.0.0'} - self.plugin.update_or_create(meta) - post_mock.assert_called_once_with('plugins/', meta) - get_for_update_mock.assert_called_once_with(meta) - self.assertFalse(put_mock.called) - - @patch.object(Plugins, 'get_plugin_for_update', return_value=None) - @patch.object(Plugins.connection, 'post_request_raw', - return_value=MagicMock( - status_code=409, - **{'json.return_value': {'id': 99}})) - @patch.object(Plugins.connection, 'put_request', return_value='put_return') - def test_update_or_create_updates_without_force( - self, put_mock, post_mock, get_for_update_mock): - meta = {'id': 99, 'version': '1.0.0', 'package_version': '2.0.0', - 'title': 'Plugin title'} - self.assertRaises(SystemExit, - self.plugin.update_or_create, - meta, - force=False) - - @patch.object(Plugins, 'get_plugin_for_update', return_value=None) - @patch.object(Plugins.connection, 'post_request_raw', - return_value=MagicMock( - status_code=409, - **{'json.return_value': {'message': '{"id": 99}'}})) - @patch.object(Plugins.connection, 'put_request', return_value='put_return') - def test_update_or_create_updates_with_force( - self, put_mock, post_mock, get_for_update_mock): - meta = {'id': 99, 'version': '1.0.0', 'package_version': '2.0.0'} - self.assertEqual( - self.plugin.update_or_create(meta, force=True), - 'put_return') - post_mock.assert_called_once_with('plugins/', meta) - get_for_update_mock.assert_called_once_with(meta) - put_mock.assert_called_once_with('plugins/99', meta) - - @patch.object(Plugins, 'get_all_data') - def test_get_plugin_for_update(self, get_mock): - plugin_to_be_found = {'name': 'name', 'version': '2.2.0', - 'package_version': '2.0.0'} - - get_mock.return_value = [ - # Different major version - {'name': 'name', 'version': '2.3.0', - 'package_version': '2.0.0'}, - {'name': 'name', 'version': '2.1.0', - 'package_version': '2.0.0'}, - # Different name - {'name': 'different_name', 'version': '2.2.99', - 'package_version': '2.0.0'}, - # Package version is not updatable - {'name': 'name', 'version': '2.2.100', - 'package_version': '1.0.0'}, - plugin_to_be_found] - - self.assertEqual( - self.plugin.get_plugin_for_update( - {'name': 'name', - 'version': '2.2.99', - 'package_version': '2.0.0'}), - plugin_to_be_found) - - # Required plugin has not updatable package version - self.assertIsNone(self.plugin.get_plugin_for_update( - {'name': 'name', 'version': '2.2.99', 'package_version': '1.0.0'})) - - # Plugin does not exist - self.assertIsNone(self.plugin.get_plugin_for_update( - {'name': 'name2', 'version': '2.2.9', 'package_version': '2.0.0'})) - - def test_is_updatable(self): - for updatable in ['2.0.0', '2.0.1', '99.99.99']: - self.assertTrue(self.plugin.is_updatable(updatable)) - - for is_not_updatable in ['0.0.1', '1.0.0', '1.99.99']: - self.assertFalse(self.plugin.is_updatable(is_not_updatable)) - - @patch.object(Plugins, 'get_all_data', - return_value=[{'name': 'name1', 'version': '1.0.0'}, - {'name': 'name2', 'version': '1.0.1'}, - {'name': 'name2', 'version': '1.0.0'}]) - def test_get_plugin(self, get_mock): - self.assertEqual(self.plugin.get_plugin('name2', '1.0.0'), - {'name': 'name2', 'version': '1.0.0'}) - get_mock.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.find_exec') - @patch('fuelclient.objects.plugins.subprocess.Popen') - def test_raise_error_if_not_master(self, mpop, mfe): - plugins.IS_MASTER = None - process = MagicMock() - mfe.return_value = '/bin/rpm' - mpop.return_value = process - process.poll.return_value = 0 - self.assertIsNone(plugins.raise_error_if_not_master()) - mpop.assert_called_once_with( - ['/bin/rpm', '-q', plugins.FUEL_PACKAGE], - stdout=mock.ANY, stderr=mock.ANY) - process.poll.assert_called_once_with() - process.communicate.assert_called_once_with() - - @patch('fuelclient.objects.plugins.utils.find_exec') - @patch('fuelclient.objects.plugins.subprocess.Popen') - def test_raise_error_if_not_master_fuel_not_installed(self, mpop, mfe): - plugins.IS_MASTER = None - process = MagicMock() - mpop.return_value = process - process.poll.return_value = 1 - self.assertRaises(error.WrongEnvironmentError, - plugins.raise_error_if_not_master) - - @patch('fuelclient.objects.plugins.utils.find_exec') - def test_raise_error_if_not_master_rpm_not_found(self, mfe): - plugins.IS_MASTER = None - mfe.return_value = None - self.assertRaises(error.WrongEnvironmentError, - plugins.raise_error_if_not_master) - - @patch('fuelclient.objects.plugins.os.access') - @patch('fuelclient.objects.plugins.os.path.isfile') - def test_find_exec(self, misf, macc): - misf.side_effect = [False, True, True] - macc.side_effect = [False, True] - # The combination will be like: - # 1) /foo/program does not exist - # 2) /bar/program does exist but isn't executable - # 3) /baz/program does exist and is executable - # So the function is to search 'program' in paths /foo, /bar, /baz - # and return /baz/program - self.useFixture(fixtures.EnvironmentVariable('PATH', '/foo:/bar:/baz')) - self.assertEqual('/baz/program', plugins.utils.find_exec('program')) - - @patch('fuelclient.objects.plugins.os.access') - @patch('fuelclient.objects.plugins.os.path.isfile') - def test_find_exec_not_found(self, misf, macc): - misf.return_value = False - self.useFixture(fixtures.EnvironmentVariable('PATH', '/foo')) - self.assertIsNone(plugins.utils.find_exec('program')) diff --git a/fuelclient/tests/unit/v1/test_release_networks_action.py b/fuelclient/tests/unit/v1/test_release_networks_action.py deleted file mode 100644 index d9b19ccb..00000000 --- a/fuelclient/tests/unit/v1/test_release_networks_action.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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. - -from mock import patch -import requests_mock as rm - -from fuelclient.tests.unit.v1 import base - - -API_INPUT = {'config': 'neutron'} -API_OUTPUT = 'config: neutron\n' - - -@patch('fuelclient.cli.serializers.open', create=True) -@patch('fuelclient.cli.actions.base.os') -class TestReleaseNetworkActions(base.UnitTestCase): - - def test_release_network_download(self, mos, mopen): - self.m_request.get(rm.ANY, json=API_INPUT) - self.execute(['fuel', 'rel', '--rel', '1', '--network', '--download']) - mopen().__enter__().write.assert_called_once_with(API_OUTPUT) - - def test_release_network_upload(self, mos, mopen): - mopen().__enter__().read.return_value = API_OUTPUT - put = self.m_request.put('/api/v1/releases/1/networks', json={}) - self.execute(['fuel', 'rel', '--rel', '1', '--network', '--upload']) - - self.assertTrue(put.called) - self.assertEqual(put.last_request.json(), API_INPUT) diff --git a/fuelclient/tests/unit/v1/test_roles.py b/fuelclient/tests/unit/v1/test_roles.py deleted file mode 100644 index a4de90c4..00000000 --- a/fuelclient/tests/unit/v1/test_roles.py +++ /dev/null @@ -1,175 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from mock import patch -import yaml - -from fuelclient.cli.serializers import Serializer -from fuelclient.tests.unit.v1 import base - -API_IN = """name: my_role -""" - -API_OUT = yaml.load(API_IN) - - -class TestRoleActions(base.UnitTestCase): - - owner_id = 2 - - def test_list_release_roles(self): - url = '/api/v1/releases/{0}/roles/'.format(self.owner_id) - cmd = 'fuel role --rel {0}'.format(self.owner_id) - get_request = self.m_request.get(url, json=[API_OUT]) - - self.execute(cmd.split()) - - self.assertTrue(get_request.called) - self.assertIn(url, get_request.last_request.url) - - def test_list_cluster_roles(self): - url = '/api/v1/clusters/{0}/roles/'.format(self.owner_id) - cmd = 'fuel role --env {0}'.format(self.owner_id) - get_request = self.m_request.get(url, json=[API_OUT]) - - self.execute(cmd.split()) - - self.assertTrue(get_request.called) - self.assertIn(url, get_request.last_request.url) - - @patch('fuelclient.cli.serializers.open', create=True) - def test_get_release_role(self, mopen): - url = '/api/v1/releases/{0}/roles/my_role/'.format(self.owner_id) - cmd = 'fuel role --role my_role --file myfile.yaml --rel {0}'.format( - self.owner_id) - get_request = self.m_request.get(url, json=API_OUT) - - self.execute(cmd.split()) - - mopen().__enter__().write.assert_called_once_with(API_IN) - self.assertTrue(get_request.called) - self.assertIn(url, get_request.last_request.url) - - @patch('fuelclient.cli.serializers.open', create=True) - def test_get_cluster_role(self, mopen): - url = '/api/v1/clusters/{0}/roles/my_role/'.format(self.owner_id) - cmd = 'fuel role --role my_role --file myfile.yaml --env {0}'.format( - self.owner_id) - get_request = self.m_request.get(url, json=API_OUT) - - self.execute(cmd.split()) - - mopen().__enter__().write.assert_called_once_with(API_IN) - self.assertTrue(get_request.called) - self.assertIn(url, get_request.last_request.url) - - @patch('fuelclient.cli.serializers.open', create=True) - def test_create_release_role(self, mopen): - url = '/api/v1/releases/{0}/roles/'.format(self.owner_id) - cmd = 'fuel role --create --file myfile.yaml --rel {0}'.format( - self.owner_id) - mopen().__enter__().read.return_value = API_IN - post_request = self.m_request.post(url, json=API_OUT) - - self.execute(cmd.split()) - - self.assertTrue(post_request.called) - self.assertIn(url, post_request.last_request.url) - self.assertEqual( - API_OUT, post_request.last_request.json()) - - @patch('fuelclient.cli.serializers.open', create=True) - def test_create_cluster_role(self, mopen): - url = '/api/v1/clusters/{0}/roles/'.format(self.owner_id) - cmd = 'fuel role --create --file myfile.yaml --env {0}'.format( - self.owner_id) - mopen().__enter__().read.return_value = API_IN - post_request = self.m_request.post(url, json=API_OUT) - - self.execute(cmd.split()) - - self.assertTrue(post_request.called) - self.assertIn(url, post_request.last_request.url) - self.assertEqual( - API_OUT, post_request.last_request.json()) - - @patch('fuelclient.cli.serializers.open', create=True) - def test_update_release_role(self, mopen): - url = '/api/v1/releases/{0}/roles/my_role/'.format(self.owner_id) - cmd = 'fuel role --update --file myfile.yaml --rel {0}'.format( - self.owner_id) - mopen().__enter__().read.return_value = API_IN - put_request = self.m_request.put(url, json=API_OUT) - - self.execute(cmd.split()) - - self.assertTrue(put_request.called) - self.assertIn(url, put_request.last_request.url) - self.assertEqual( - API_OUT, put_request.last_request.json()) - - @patch('fuelclient.cli.serializers.open', create=True) - def test_update_cluster_role(self, mopen): - url = '/api/v1/clusters/{0}/roles/my_role/'.format(self.owner_id) - cmd = 'fuel role --update --file myfile.yaml --env {0}'.format( - self.owner_id) - mopen().__enter__().read.return_value = API_IN - put_request = self.m_request.put(url, json=API_OUT) - - self.execute(cmd.split()) - - self.assertTrue(put_request.called) - self.assertIn(url, put_request.last_request.url) - self.assertEqual( - API_OUT, put_request.last_request.json()) - - def test_delete_release_role(self): - url = '/api/v1/releases/{0}/roles/my_role/'.format(self.owner_id) - cmd = 'fuel role --delete --role my_role --rel {0}'.format( - self.owner_id) - delete_request = self.m_request.delete(url, json=API_OUT) - - self.execute(cmd.split()) - - self.assertTrue(delete_request.called) - self.assertIn(url, delete_request.last_request.url) - - def test_delete_cluster_role(self): - url = '/api/v1/clusters/{0}/roles/my_role/'.format(self.owner_id) - cmd = 'fuel role --delete --role my_role --env {0}'.format( - self.owner_id) - delete_request = self.m_request.delete(url, json=API_OUT) - - self.execute(cmd.split()) - - self.assertTrue(delete_request.called) - self.assertIn(url, delete_request.last_request.url) - - def test_formatting_for_list_roles(self): - url = '/api/v1/releases/{0}/roles/'.format(self.owner_id) - cmd = 'fuel role --rel {0}'.format(self.owner_id) - get_request = self.m_request.get(url, json=[API_OUT]) - - with patch.object(Serializer, 'print_to_output') as mock_print: - with patch('fuelclient.cli.actions.role.format_table') \ - as format_table_mock: - self.execute(cmd.split()) - - self.assertTrue(get_request.called) - self.assertIn(url, get_request.last_request.url) - - format_table_mock.assert_called_once_with( - [API_OUT], acceptable_keys=('name',)) - mock_print.assert_called_once_with( - [API_OUT], format_table_mock.return_value) diff --git a/fuelclient/tests/unit/v1/test_snapshot.py b/fuelclient/tests/unit/v1/test_snapshot.py deleted file mode 100644 index 6e33faa3..00000000 --- a/fuelclient/tests/unit/v1/test_snapshot.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from mock import call -from mock import Mock -from mock import patch - -from fuelclient.tests.unit.v1 import base - - -class TestSnapshot(base.UnitTestCase): - - def setUp(self): - super(TestSnapshot, self).setUp() - - self.mtask = Mock(status='ready', data={'message': ''}) - self.mtask.connection = Mock(root='') - - @patch('fuelclient.cli.actions.snapshot.SnapshotTask.get_default_config') - @patch('sys.stdout') - def test_get_default_config(self, mstdout, mconf): - - mconf.return_value = {'key': 'value'} - - self.execute(['fuel', 'snapshot', '--conf']) - self.assertEqual(mstdout.write.call_args_list, [call('key: value\n')]) - - @patch('fuelclient.cli.actions.snapshot.SnapshotTask.start_snapshot_task') - @patch('sys.stdin') - @patch('sys.stdout') - def test_create_snapshot_with_provided_conf(self, mstdout, mstdin, mstart): - conf = 'key: value\n' - - mstdin.isatty.return_value = False - mstdin.read.return_value = conf - - mstart.return_value = self.mtask - - self.execute(['fuel', 'snapshot']) - - mstart.assert_called_once_with({'key': 'value'}) - self.assertEqual(mstdin.read.call_count, 1) - msg = mstdout.write.call_args_list[2][0][0] - self.assertIn("Diagnostic snapshot can be downloaded from", msg) - - @patch('fuelclient.cli.actions.snapshot.SnapshotTask.start_snapshot_task') - @patch('sys.stdin') - @patch('sys.stdout') - def test_create_snapshot_without_conf(self, mstdout, mstdin, mstart): - - mstdin.isatty.return_value = True - - mstart.return_value = self.mtask - - self.execute(['fuel', 'snapshot']) - - mstart.assert_called_once_with({}) - msg = mstdout.write.call_args_list[2][0][0] - self.assertIn("Diagnostic snapshot can be downloaded from", msg) - - @patch('fuelclient.cli.actions.snapshot.SnapshotTask.start_snapshot_task') - @patch('sys.stdin') - @patch('sys.stderr') - def test_create_snapshot_when_task_is_failed( - self, mstderr, mstdin, mstart): - mstdin.isatty.return_value = True - - mdata = {'message': 'mock task message'} - self.mtask.status = 'error' - self.mtask.data = mdata - - mstart.return_value = self.mtask - - self.execute(['fuel', 'snapshot']) - - err_msg = ("Snapshot generating task ended with error. " - "Task message: {0}".format(mdata['message'])) - mstderr.write.called_once_with(err_msg) - - @patch('fuelclient.cli.actions.snapshot.SnapshotTask.start_snapshot_task') - @patch('sys.stdin') - @patch('sys.stdout') - def test_downloadable_snapshot_url(self, mstdout, mstdin, mstart): - expected_url = 'http://127.0.0.1:8000' - mdata = {'message': '/api/dump/mock-fuel-snapshot.tar.xz'} - mstdin.isatty.return_value = True - self.mtask.connection.root = expected_url - self.mtask.data = mdata - - mstart.return_value = self.mtask - - self.execute(['fuel', 'snapshot']) - - expected_msg = ("...Completed...\n" - "Diagnostic snapshot can be downloaded from " - "{}{}".format(expected_url, mdata['message'])) - msg = mstdout.write.call_args_list[2][0][0] - self.assertEqual(expected_msg, msg) diff --git a/fuelclient/tests/unit/v1/test_token_action.py b/fuelclient/tests/unit/v1/test_token_action.py deleted file mode 100644 index 10712925..00000000 --- a/fuelclient/tests/unit/v1/test_token_action.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 io - -import mock - -from fuelclient.tests.unit.v1 import base - - -class TestPluginsActions(base.UnitTestCase): - - @mock.patch('fuelclient.cli.actions.token.DefaultAPIClient') - def test_token_action(self, mAPIClient): - with mock.patch('sys.stdout', new=io.StringIO()) as mstdout: - token = u'token123' - mauth_token = mock.PropertyMock(return_value=token) - type(mAPIClient).auth_token = mauth_token - - self.execute(['fuel', 'token']) - - self.assertEqual(mauth_token.call_count, 1) - self.assertEqual(mstdout.getvalue(), token) diff --git a/fuelclient/tests/unit/v1/test_user_action.py b/fuelclient/tests/unit/v1/test_user_action.py deleted file mode 100644 index a78cecc7..00000000 --- a/fuelclient/tests/unit/v1/test_user_action.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2015 Mirantis, 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 mock - -from fuelclient.cli.actions.user import UserAction -from fuelclient.cli.error import ArgumentException -from fuelclient.tests.unit.v1 import base - - -class TestChangePassword(base.UnitTestCase): - - def assert_print(self, print_mock, result, msg): - print_mock.assert_called_once_with(result, msg) - - def test_get_password_from_prompt(self): - user_action = UserAction() - passwd = 'secret!' - with mock.patch('fuelclient.cli.actions.user.getpass', - return_value=passwd): - user_passwd = user_action._get_password_from_prompt() - - self.assertEqual(passwd, user_passwd) - - @mock.patch('fuelclient.cli.actions.user.getpass', - side_effect=['pwd', 'otherpwd']) - def test_get_password_from_prompt_different_passwords(self, mgetpass): - user_action = UserAction() - with self.assertRaisesRegexp( - ArgumentException, 'Passwords are not the same'): - user_action._get_password_from_prompt() - - @mock.patch('fuelclient.cli.serializers.Serializer.print_to_output') - @mock.patch('fuelclient.cli.actions.user.fuelclient_settings') - @mock.patch('fuelclient.cli.actions.user.DefaultAPIClient') - def test_change_password(self, mapiclient, settings_mock, print_mock): - user_action = UserAction() - params = mock.Mock() - params.newpass = None - password = 'secret' - conf_file = '/tmp/fuel_client.yaml' - settings_mock.get_settings.return_value = mock.Mock( - user_settings=conf_file) - - with mock.patch('fuelclient.cli.actions.user.getpass', - return_value=password) as mgetpass: - user_action.change_password(params) - - calls = [ - mock.call("Changing password for Fuel User.\nNew Password:"), - mock.call("Retype new Password:"), - ] - - mgetpass.assert_has_calls(calls) - mapiclient.update_own_password.assert_called_once_with(password) - - msg = "\nPassword changed.\nPlease note that configuration " \ - "is not automatically updated.\nYou may want to update " \ - "{0}.".format(conf_file) - - self.assert_print( - print_mock, - None, - msg) - - @mock.patch('fuelclient.cli.actions.user.DefaultAPIClient') - def test_change_password_w_newpass(self, mapiclient): - user_action = UserAction() - params = mock.Mock() - params.newpass = 'secret' - user_action.change_password(params) - mapiclient.update_own_password.assert_called_once_with(params.newpass) diff --git a/fuelclient/tests/unit/v1/test_vip_action.py b/fuelclient/tests/unit/v1/test_vip_action.py deleted file mode 100644 index 2fdd6d8a..00000000 --- a/fuelclient/tests/unit/v1/test_vip_action.py +++ /dev/null @@ -1,214 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock -import six -import yaml - -from fuelclient.tests.unit.v1 import base - -ENV_OUTPUT = { - "status": "new", - "is_customized": False, - "release_id": 2, - "ui_settings": { - "sort": [{"roles": "asc"}], - "sort_by_labels": [], - "search": "", - "filter_by_labels": {}, - "filter": {}, - "view_mode": "standard" - }, - "is_locked": False, - "fuel_version": "8.0", - "net_provider": "neutron", - "mode": "ha_compact", - "components": [], - "changes": [ - {"node_id": None, "name": "attributes"}, - {"node_id": None, "name": "networks"}], - "id": 6, "name": "test_not_deployed"} - - -MANY_VIPS_YAML = '''- id: 5 - network: 3 - node: null - ip_addr: 192.169.1.33 - vip_name: public - vip_namespace: haproxy - is_user_defined: false -- id: 6 - network: 3 - node: null - ip_addr: 192.169.1.34 - vip_namespace: null - vip_name: private - is_user_defined: true -''' - -ONE_VIP_YAML = ''' -- id: 5 - network: 3 - node: null - ip_addr: 192.169.1.33 - vip_name: public - vip_namespace: haproxy - is_user_defined: false -''' - - -@mock.patch('fuelclient.cli.serializers.open', create=True) -@mock.patch('fuelclient.cli.actions.base.os') -class TestVIPActions(base.UnitTestCase): - - def test_env_vips_download(self, mos, mopen): - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - url = '/api/v1/clusters/1/network_configuration/ips/vips/' - get_request = self.m_request.get( - url, - json=yaml.load(MANY_VIPS_YAML)) - self.execute('fuel vip --env 1 --download'.split()) - self.assertTrue(get_request.called) - self.assertEqual(1, mopen().__enter__().write.call_count) - self.assertEqual( - yaml.safe_load(MANY_VIPS_YAML), - yaml.safe_load(mopen().__enter__().write.call_args[0][0]), - ) - - def test_env_vips_download_with_network_id(self, mos, mopen): - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - url = '/api/v1/clusters/1/network_configuration/ips/vips/' - get_request = self.m_request.get( - url, - json=yaml.load(MANY_VIPS_YAML)) - self.execute('fuel vip --env 1 --network 3 --download'.split()) - self.assertTrue(get_request.called) - self.assertEqual(1, mopen().__enter__().write.call_count) - self.assertEqual( - yaml.safe_load(MANY_VIPS_YAML), - yaml.safe_load(mopen().__enter__().write.call_args[0][0]), - ) - - def test_env_vips_download_with_network_role(self, mos, mopen): - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - url = '/api/v1/clusters/1/network_configuration/ips/vips/' - get_request = self.m_request.get( - url, - json=yaml.load(MANY_VIPS_YAML)) - self.execute( - 'fuel vip --env 1 --network-role some/role --download'.split()) - self.assertTrue(get_request.called) - self.assertEqual(1, mopen().__enter__().write.call_count) - self.assertEqual( - yaml.safe_load(MANY_VIPS_YAML), - yaml.safe_load(mopen().__enter__().write.call_args[0][0]), - ) - - def test_env_single_vip_download(self, mos, mopen): - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - url = '/api/v1/clusters/1/network_configuration/ips/5/vips/' - get_request = self.m_request.get( - url, - json=yaml.safe_load(ONE_VIP_YAML)[0] - ) - self.execute('fuel vip --env 1 --ip-address-id 5 --download'.split()) - - self.assertTrue(get_request.called) - self.assertEqual(1, mopen().__enter__().write.call_count) - - self.assertEqual( - yaml.safe_load(ONE_VIP_YAML), - yaml.safe_load(mopen().__enter__().write.call_args[0][0]), - ) - self.assertIn( - 'vips_1.yaml', - mopen.call_args_list[0][0][0] - ) - - def test_env_single_vip_download_to_file(self, mos, mopen): - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - url = '/api/v1/clusters/1/network_configuration/ips/5/vips/' - get_request = self.m_request.get( - url, - json=yaml.safe_load(ONE_VIP_YAML)[0] - ) - self.execute('fuel vip --env 1 --ip-address-id 5 ' - '--download --file vips.yaml'.split()) - - self.assertTrue(get_request.called) - self.assertEqual(1, mopen().__enter__().write.call_count) - - self.assertEqual( - yaml.safe_load(ONE_VIP_YAML), - yaml.safe_load(mopen().__enter__().write.call_args[0][0]), - ) - self.assertEqual( - 'vips.yaml', - mopen.call_args_list[0][0][0] - ) - - def check_request(self, request_mock, url): - self.assertEqual(request_mock.call_count, 1) - self.assertIn(url, request_mock.last_request.url) - - def test_vips_upload(self, mos, mopen): - url = '/api/v1/clusters/1/network_configuration/ips/vips/' - mopen().__enter__().read.return_value = MANY_VIPS_YAML - self.m_request.get('/api/v1/clusters/1/', json=ENV_OUTPUT) - request_put = self.m_request.put(url, json={}) - - file_path = 'vips.yaml' - - with mock.patch('fuelclient.objects.environment.os') as env_os: - env_os.path.exists.return_value = True - self.execute(['fuel', 'vip', '--env', '1', '--upload', file_path]) - self.assertEqual(env_os.path.exists.call_count, 1) - self.check_request(request_put, url) - # FileFormatBasedSerializer.read_from_file must not modify given - # file path string - self.assertEqual(file_path, mopen.call_args[0][0]) - - def test_vips_upload_bad_path(self, mos, mopen): - with mock.patch('sys.stderr', new=six.moves.cStringIO()) as mstderr: - with mock.patch('fuelclient.objects.environment.os') as env_os: - env_os.path.exists.return_value = False - self.assertRaises( - SystemExit, - self.execute, - 'fuel vip --env 1 --upload vips_1.yaml'.split() - ) - self.assertIn("doesn't exist", mstderr.getvalue()) - - def test_create_vip(self, *_): - url = '/api/v1/clusters/1/network_configuration/ips/vips/' - request_post = self.m_request.post(url, json={}) - - env_id = 1 - vip_data = { - "ip_addr": "127.0.0.1", - "network": -1, - "vip_name": 'test', - "vip_namespace": 'test-namespace' - } - - self.execute(["fuel", "--env", str(env_id), "vip", "create", - "--ip-addr", vip_data['ip_addr'], - "--network", str(vip_data['network']), - "--name", vip_data['vip_name'], - "--namespace", vip_data['vip_namespace']]) - - self.check_request(request_post, url) - self.assertEqual(request_post.last_request.json(), vip_data) diff --git a/fuelclient/tests/unit/v2/__init__.py b/fuelclient/tests/unit/v2/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/unit/v2/cli/__init__.py b/fuelclient/tests/unit/v2/cli/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/unit/v2/cli/test_deployment_graph.py b/fuelclient/tests/unit/v2/cli/test_deployment_graph.py deleted file mode 100644 index f70dee08..00000000 --- a/fuelclient/tests/unit/v2/cli/test_deployment_graph.py +++ /dev/null @@ -1,392 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock -import six -import yaml - -from fuelclient.cli import error -from fuelclient.tests.unit.v2.cli import test_engine - -TASKS_YAML = '''- id: custom-task-1 - type: puppet - parameters: - param: value -- id: custom-task-2 - type: puppet - parameters: - param: value -''' - -GRAPH_YAML = '''tasks: - - id: custom-task-1 - type: puppet - parameters: - param: value - - id: custom-task-2 - type: puppet - parameters: - param: value -node_filter: $.pending_deletion -''' - -GRAPH_METADATA_YAML = ''' -node_filter: $.pending_addition -on_success: - node_attributes: - status: provisioned -''' - - -class TestGraphActions(test_engine.BaseCLITest): - @mock.patch('fuelclient.commands.graph.os') - def _test_cmd(self, method, cmd_line, expected_kwargs, os_m): - os_m.exists.return_value = True - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - m_open = mock.mock_open(read_data=TASKS_YAML) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True): - self.exec_command('graph {0} {1}'.format(method, cmd_line)) - self.m_get_client.assert_called_once_with('graph', mock.ANY) - self.m_client.__getattr__(method).assert_called_once_with( - **expected_kwargs) - - def test_upload(self): - self._test_cmd( - 'upload', '--env 1 --file new_tasks.yaml -t test', dict( - data=yaml.load(TASKS_YAML), - related_model='clusters', - related_id=1, - graph_type='test' - ) - ) - self._test_cmd( - 'upload', '--release 1 --file new_tasks.yaml -t test', dict( - data=yaml.load(TASKS_YAML), - related_model='releases', - related_id=1, - graph_type='test' - ) - ) - self._test_cmd( - 'upload', '--plugin 1 --file new_tasks.yaml -t test', dict( - data=yaml.load(TASKS_YAML), - related_model='plugins', - related_id=1, - graph_type='test' - ) - ) - self._test_cmd( - 'upload', - '--plugin 1 --file tasks.yaml --graph-type custom_type', - dict( - data=yaml.load(TASKS_YAML), - related_model='plugins', - related_id=1, - graph_type='custom_type' - ) - ) - - @mock.patch('fuelclient.commands.graph.os') - def test_graph_upload_from_file(self, os_m): - os_m.path.exists.return_value = True - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - m_open = mock.mock_open(read_data=GRAPH_YAML) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True): - self.exec_command( - 'graph upload --env 1 --file new_graph.yaml -t custom' - ) - self.m_get_client.assert_called_once_with('graph', mock.ANY) - self.m_client.upload.assert_called_once_with( - data=yaml.load(GRAPH_YAML), - related_model='clusters', - related_id=1, - graph_type='custom' - ) - - @mock.patch('fuelclient.commands.graph.os') - @mock.patch('fuelclient.commands.graph.iterfiles') - @mock.patch('fuelclient.commands.graph.Serializer') - def test_graph_upload_from_dir(self, serializers_m, iterfiles_m, os_m): - tasks = yaml.load(TASKS_YAML) - graph_data = yaml.load(GRAPH_METADATA_YAML) - os_m.path.exists.return_value = True - os_m.path.isdir.return_value = True - serializers_m().read_from_full_path.side_effect = [graph_data, tasks] - iterfiles_m.return_value = ['tasks.yaml'] - - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - m_open = mock.mock_open(read_data=GRAPH_YAML) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True): - self.exec_command( - 'graph upload --release 1 --dir /graph/provision -t provision' - ) - self.m_get_client.assert_called_once_with('graph', mock.ANY) - self.m_client.upload.assert_called_once_with( - data=dict(graph_data, tasks=tasks), - related_model='releases', - related_id=1, - graph_type='provision' - ) - - @mock.patch('fuelclient.commands.graph.os') - @mock.patch('fuelclient.commands.graph.iterfiles') - def test_graph_upload_from_dir_fail(self, iterfiles_m, os_m): - os_m.path.isdir.return_value = True - os_m.path.exists.side_effect = [True, False] - iterfiles_m.return_value = [] - args = 'graph upload --release 1 --dir /graph/provision -t provision' - - self.assertRaisesRegexp(error.ActionException, - "Nothing to upload", - self.exec_command, args) - - @mock.patch('sys.stderr') - def test_upload_fail(self, mocked_stderr): - cmd = 'graph upload --file new_graph.yaml -t test' - self.assertRaises(SystemExit, self.exec_command, cmd) - self.assertIn('-e/--env -r/--release -p/--plugin', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_execute(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types graph1 graph2 --nodes 1 2 3', - dict( - env_id=1, - graph_types=['graph1', 'graph2'], - nodes=[1, 2, 3], - task_names=None, - dry_run=False, - noop_run=False, - force=False, - debug=False, - subgraphs=None - ) - ) - - def test_execute_w_dry_run(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types graph1 graph2 --nodes 1 2 3 --dry-run', - dict( - env_id=1, - graph_types=['graph1', 'graph2'], - nodes=[1, 2, 3], - task_names=None, - dry_run=True, - noop_run=False, - force=False, - debug=False, - subgraphs=None - ) - ) - - def test_execute_w_force(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types graph1 --force', - dict( - env_id=1, - graph_types=['graph1'], - nodes=None, - task_names=None, - dry_run=False, - noop_run=False, - force=True, - debug=False, - subgraphs=None - ) - ) - - def test_execute_w_task_names(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types graph1 --task-names task1 task2', - dict( - env_id=1, - graph_types=['graph1'], - nodes=None, - task_names=['task1', 'task2'], - dry_run=False, - noop_run=False, - force=False, - debug=False, - subgraphs=None - ) - ) - - def test_execute_w_noop_run(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types graph1 graph2 --nodes 1 2 3 --noop', - dict( - env_id=1, - graph_types=['graph1', 'graph2'], - nodes=[1, 2, 3], - task_names=None, - dry_run=False, - noop_run=True, - force=False, - debug=False, - subgraphs=None - ) - ) - - def test_execute_w_trace(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types graph1 --trace', - dict( - env_id=1, - graph_types=['graph1'], - nodes=None, - task_names=None, - dry_run=False, - noop_run=False, - force=False, - debug=True, - subgraphs=None - ) - ) - - def test_execute_w_dry_run_subgraph(self): - self._test_cmd( - 'execute', - '--env 1 --graph-types custom_graph --nodes 1 2 3 ' - '--dry-run --subgraphs primary-database/1,3:keystone-db/1-2,5' - ' openstack-controller', - dict( - env_id=1, - force=False, - graph_types=['custom_graph'], - nodes=[1, 2, 3], - noop_run=False, - dry_run=True, - subgraphs=['primary-database/1,3:keystone-db/1-2,5', - 'openstack-controller'], - task_names=None, - debug=False - ) - ) - - def test_execute_with_json_output(self): - self.m_client.execute.return_value = mock.MagicMock( - data={'id': 1} - ) - with mock.patch('sys.stdout') as stdout_mock: - self.exec_command( - 'graph execute --env 1 --graph-types graph1 --format=json' - ) - stdout_mock.write.assert_called_with('{\n "id": 1\n}\n') - - def test_download(self): - self.m_client.download.return_value = yaml.safe_load(TASKS_YAML) - - self._test_cmd( - 'download', - '--env 1 --all --file existing_graph.yaml -t custom_graph', - dict( - env_id=1, - level='all', - graph_type='custom_graph' - ) - ) - - @mock.patch('json.dumps') - def test_download_json(self, m_dumps): - env_id = 1 - graph_data = [{'id': 1}] - args = 'graph download --env {0} --all --format json'.format(env_id) - expected_path = '/tmp/all_graph_{0}.json'.format(env_id) - - self.m_client.download.return_value = graph_data - - m_open = mock.mock_open() - with mock.patch('os.path.abspath', return_value='/tmp'): - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dumps.assert_called_once_with(graph_data, indent=4) - self.m_get_client.assert_called_once_with('graph', mock.ANY) - - @mock.patch('sys.stderr') - def test_download_fail(self, mocked_stderr): - cmd = 'graph download --env 1' - self.assertRaises(SystemExit, self.exec_command, cmd) - self.assertIn('-a/--all -c/--cluster -p/--plugins -r/--release', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_list(self): - with mock.patch('sys.stdout', new=six.moves.cStringIO()) as m_stdout: - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - self.m_client.list.return_value = [ - { - 'name': 'updated-graph-name', - 'tasks': [{ - 'id': 'test-task2', - 'type': 'puppet', - 'task_name': 'test-task2', - 'version': '2.0.0' - }], - 'relations': [{ - 'model': 'cluster', - 'model_id': 370, - 'type': 'custom-graph' - }], - 'id': 1 - } - ] - self.exec_command( - 'graph list --env 1 --release --plugins --cluster') - self.m_get_client.assert_called_once_with('graph', mock.ANY) - - self.assertIn('1', m_stdout.getvalue()) - self.assertIn('updated-graph-name', m_stdout.getvalue()) - self.assertIn('custom-graph', m_stdout.getvalue()) - self.assertIn('test-task2', m_stdout.getvalue()) - - self.exec_command('graph list --release') - self.exec_command('graph list --plugins') - self.exec_command('graph list --cluster') - self.exec_command('graph list') - - self.m_client.list.assert_has_calls([ - mock.call(env_id=1, filters=['release', 'plugin', 'cluster']), - mock.call(env_id=None, filters=['release']), - mock.call(env_id=None, filters=['plugin']), - mock.call(env_id=None, filters=['cluster']), - mock.call(env_id=None, filters=None) - ]) - - def test_delete(self): - self._test_cmd( - 'delete', - '--env 1 --graph-type custom_graph', - dict( - graph_type='custom_graph', - related_id=1, - related_model='clusters' - ) - ) diff --git a/fuelclient/tests/unit/v2/cli/test_engine.py b/fuelclient/tests/unit/v2/cli/test_engine.py deleted file mode 100644 index 5b3b0a93..00000000 --- a/fuelclient/tests/unit/v2/cli/test_engine.py +++ /dev/null @@ -1,171 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 shlex -import sys - -import mock -from oslotest import base as oslo_base - -import fuelclient -from fuelclient.commands import environment as env -from fuelclient.commands import node as node -from fuelclient import main as main_mod -from fuelclient.tests import utils - - -class BaseCLITest(oslo_base.BaseTestCase): - """Base class for testing the new CLI - - It mocks the whole API layer in order to be sure the - tests test only the stuff which is responsible for - the command line application. That allows to find bugs - more precisely and not confuse them with the bugs in the - API wrapper. - - """ - def setUp(self): - super(BaseCLITest, self).setUp() - - self._get_client_patcher = mock.patch.object(fuelclient, 'get_client') - self.m_get_client = self._get_client_patcher.start() - - self.m_client = mock.MagicMock() - self.m_get_client.return_value = self.m_client - self.addCleanup(self._get_client_patcher.stop) - - def exec_command(self, command=''): - """Executes fuelclient with the specified arguments.""" - argv = shlex.split(command) - if '--debug' not in argv: - argv = ['--debug'] + argv - - return main_mod.main(argv=argv) - - def exec_command_interactive(self, commands): - """Executes specified commands in one sesstion of interactive mode - - Starts Fuel Client's interactive console and passes - supplied commands there. - - :param commands: The list of commands to execute in the - Fuel Client's console. - :type commands: list of str - - """ - with mock.patch.object(sys, 'stdin') as m_stdin: - m_stdin.readline.side_effect = commands - self.exec_command() - - @mock.patch('cliff.app.App.run_subcommand') - def test_command_non_interactive(self, m_run_command): - args = ['help'] - self.exec_command(*args) - m_run_command.assert_called_once_with(args) - - @mock.patch('cliff.commandmanager.CommandManager.find_command') - def test_command_interactive(self, m_find_command): - commands = ['quit'] - - self.exec_command_interactive(commands) - m_find_command.assert_called_once_with(commands) - - @mock.patch('cliff.formatters.table.TableFormatter.emit_list') - def test_lister_sorting(self, m_emit_list): - cmd = 'env list -s status release_id' - - raw_data = [{'id': 43, - 'status': 'STATUS 2', - 'name': 'Test env 2', - 'release_id': 2}, - - {'id': 42, - 'status': 'STATUS 1', - 'name': 'Test env 1', - 'release_id': 2}, - - {'id': 44, - 'status': 'STATUS 2', - 'name': 'Test env 3', - 'release_id': 1}] - - expected_order = [1, 2, 0] - expected_data = [[raw_data[i][prop] for prop in env.EnvList.columns] - for i in expected_order] - - self.m_client.get_all.return_value = raw_data - - self.exec_command(cmd) - m_emit_list.assert_called_once_with(mock.ANY, - expected_data, - mock.ANY, - mock.ANY) - - @mock.patch('fuelclient.fuelclient_settings.' - 'FuelClientSettings.update_from_command_line_options') - def test_settings_override_called(self, m_update): - cmd = ('--os-password tpass --os-username tname --os-tenant-name tten ' - 'node list') - self.m_client.get_all.return_value = [utils.get_fake_node() - for _ in range(10)] - - self.exec_command(cmd) - - m_update.assert_called_once_with(mock.ANY) - passed_settings = m_update.call_args[0][0] - - self.assertEqual('tname', passed_settings.os_username) - self.assertEqual('tpass', passed_settings.os_password) - self.assertEqual('tten', passed_settings.os_tenant_name) - - def test_get_attribute_path(self): - cmd = node.NodeShow(None, None) - - attr_types = ('attributes', 'interfaces', 'disks') - file_format = 'json' - node_id = 42 - directory = '/test' - - for attr_type in attr_types: - expected_path = '/test/node_42/{t}.json'.format(t=attr_type) - real_path = cmd.get_attributes_path(attr_type, file_format, - node_id, directory) - - self.assertEqual(expected_path, real_path) - - def test_get_attribute_path_wrong_attr_type(self): - cmd = node.NodeShow(None, None) - - attr_type = 'wrong' - file_format = 'json' - node_id = 42 - directory = '/test' - - self.assertRaises(ValueError, - cmd.get_attributes_path, - attr_type, file_format, node_id, directory) - - def test_get_attribute_path_wrong_file_format(self): - cmd = node.NodeShow(None, None) - - attr_type = 'interfaces' - file_format = 'wrong' - node_id = 42 - directory = '/test' - - self.assertRaises(ValueError, - cmd.get_attributes_path, - attr_type, file_format, node_id, directory) diff --git a/fuelclient/tests/unit/v2/cli/test_env.py b/fuelclient/tests/unit/v2/cli/test_env.py deleted file mode 100644 index 87142f9e..00000000 --- a/fuelclient/tests/unit/v2/cli/test_env.py +++ /dev/null @@ -1,714 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 json -import mock -import yaml - -from six import moves - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_env -from fuelclient.tests.utils import fake_task -from fuelclient.v1 import environment - - -class TestEnvCommand(test_engine.BaseCLITest): - """Tests for fuel2 env * commands.""" - - def setUp(self): - super(TestEnvCommand, self).setUp() - - self.m_client.get_all.return_value = [fake_env.get_fake_env() - for i in range(10)] - self.m_client.get_by_id.return_value = fake_env.get_fake_env() - self.m_client.create.return_value = fake_env.get_fake_env() - self.m_client.update.return_value = fake_env.get_fake_env() - - def test_env_list(self): - args = 'env list' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_env_list_sorted(self): - args = 'env list -s name' - self.exec_command(args) - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_env_show(self): - args = 'env show 42' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_by_id.assert_called_once_with(42) - - def test_env_create(self): - args = 'env create -r 1 -nst gre env42' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - - m_client = self.m_client - m_client.create.assert_called_once_with(name='env42', - release_id=1, - net_segment_type='gre') - - def test_neutron_gre_deprecation_warning(self): - args = 'env create -r 1 -nst gre env42' - - with mock.patch('sys.stderr', new=moves.cStringIO()) as m_stderr: - self.exec_command(args) - self.assertIn( - "WARNING: GRE network segmentation type is deprecated " - "since 7.0 release", - m_stderr.getvalue() - ) - - def test_env_delete(self): - args = 'env delete --force 42' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.delete_by_id.assert_called_once_with(42) - - def test_env_delete_wo_force(self): - args = 'env delete 42' - - env = fake_env.get_fake_env(status='operational') - self.m_client.get_by_id.return_value = env - - with mock.patch('sys.stdout', new=moves.cStringIO()) as m_stdout: - self.exec_command(args) - self.assertIn('--force', m_stdout.getvalue()) - - def test_env_deploy(self): - dry_run = False - noop_run = False - args = 'env deploy' - - args += ' 42' - - self.exec_command(args) - - calls = list() - calls.append(mock.call.deploy_changes(42, - noop_run=noop_run, - dry_run=dry_run)) - - self.m_get_client.assert_called_with('environment', mock.ANY) - self.m_client.assert_has_calls(calls) - - def test_env_deploy_dry_run(self): - dry_run = True - noop_run = False - - args = 'env deploy -d' - args += ' 42' - - self.exec_command(args) - - calls = list() - calls.append(mock.call.deploy_changes(42, - noop_run=noop_run, - dry_run=dry_run)) - - self.m_get_client.assert_called_with('environment', mock.ANY) - self.m_client.assert_has_calls(calls) - - def test_env_deploy_noop_run(self): - dry_run = False - noop_run = True - - args = 'env deploy --noop' - args += ' 42' - - self.exec_command(args) - - calls = list() - calls.append(mock.call.deploy_changes(42, - noop_run=noop_run, - dry_run=dry_run)) - - self.m_get_client.assert_called_with('environment', mock.ANY) - self.m_client.assert_has_calls(calls) - - def test_env_redeploy(self): - dry_run = False - noop_run = False - args = 'env redeploy' - - args += ' 42' - - self.exec_command(args) - - calls = list() - calls.append(mock.call.redeploy_changes(42, - noop_run=noop_run, - dry_run=dry_run)) - - self.m_get_client.assert_called_with('environment', mock.ANY) - self.m_client.assert_has_calls(calls) - - def test_env_redeploy_dry_run(self): - dry_run = True - noop_run = False - args = 'env redeploy -d' - - args += ' 42' - - self.exec_command(args) - - calls = list() - calls.append(mock.call.redeploy_changes(42, - noop_run=noop_run, - dry_run=dry_run)) - - self.m_get_client.assert_called_with('environment', mock.ANY) - self.m_client.assert_has_calls(calls) - - def test_env_redeploy_noop_run(self): - dry_run = False - noop_run = True - args = 'env redeploy --noop' - - args += ' 42' - - self.exec_command(args) - - calls = list() - calls.append(mock.call.redeploy_changes(42, - noop_run=noop_run, - dry_run=dry_run)) - - self.m_get_client.assert_called_with('environment', mock.ANY) - self.m_client.assert_has_calls(calls) - - def test_env_reset(self): - env_id = 45 - args = 'env reset {env_id}'.format(env_id=env_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.reset.assert_called_once_with(env_id, force=False) - - def test_env_reset_force(self): - env_id = 45 - args = 'env reset {env_id} --force'.format(env_id=env_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.reset.assert_called_once_with(env_id, force=True) - - def test_env_add_nodes(self): - args = 'env add nodes -e 42 -n 24 25 -r compute cinder' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.add_nodes.assert_called_once_with(environment_id=42, - nodes=[24, 25], - roles=['compute', - 'cinder']) - - def test_env_remove_nodes_by_id(self): - args = 'env remove nodes -e 42 -n 24 25' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.remove_nodes.assert_called_once_with(environment_id=42, - nodes=[24, 25]) - - def test_env_remove_nodes_all(self): - args = 'env remove nodes -e 42 --nodes-all' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.remove_nodes.assert_called_once_with(environment_id=42, - nodes=None) - - def test_env_update(self): - self.m_client._updatable_attributes = \ - environment.EnvironmentClient._updatable_attributes - - args = 'env update -n test_name 42' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.update.assert_called_once_with(environment_id=42, - name='test_name') - - def test_env_spawn_vms(self): - env_id = 10 - args = 'env spawn-vms {0}'.format(env_id) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.spawn_vms.assert_called_once_with(env_id) - - def test_env_nodes_deploy(self): - env_id = 42 - node_ids = [43, 44] - noop_run = False - args = ('env nodes deploy ' - '--nodes {n[0]} {n[1]} --env {e}').format(e=env_id, n=node_ids) - - self.exec_command(args) - - self.m_client.deploy_nodes.return_value = fake_task.get_fake_task() - self.m_client.deploy_nodes.assert_called_once_with(env_id, node_ids, - force=False, - noop_run=noop_run) - - def test_env_nodes_deploy_force(self): - env_id = 42 - node_ids = [43, 44] - force = True - noop_run = False - args = ('env nodes deploy --force ' - '--nodes {n[0]} {n[1]} --env {e}').format(e=env_id, n=node_ids) - - self.exec_command(args) - - self.m_client.deploy_nodes.return_value = fake_task.get_fake_task() - self.m_client.deploy_nodes.assert_called_once_with(env_id, node_ids, - noop_run=noop_run, - force=force) - - def test_env_nodes_deploy_noop_run(self): - env_id = 42 - node_ids = [43, 44] - force = False - noop_run = True - args = ('env nodes deploy --noop ' - '--nodes {n[0]} {n[1]} --env {e}').format(e=env_id, n=node_ids) - - self.exec_command(args) - - self.m_client.deploy_nodes.return_value = fake_task.get_fake_task() - self.m_client.deploy_nodes.assert_called_once_with(env_id, node_ids, - force=force, - noop_run=noop_run) - - def test_env_nodes_provision(self): - env_id = 42 - node_ids = [43, 44] - args = ('env nodes provision ' - '--nodes {n[0]} {n[1]} --env {e}').format(e=env_id, n=node_ids) - - self.m_client.provision_nodes.return_value = fake_task.get_fake_task() - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.provision_nodes.assert_called_once_with(env_id, node_ids) - - def test_env_stop(self): - env_id = 45 - args = 'env stop-deployment {env_id}'.format(env_id=env_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.stop.assert_called_once_with(env_id) - - def test_env_network_verify(self): - env_id = 42 - args = 'env network verify {}'.format(env_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.verify_network.assert_called_once_with(env_id) - - @mock.patch('json.dump') - def test_env_network_download_json(self, m_dump): - args = 'env network download --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/environment_42/network.json' - - self.m_client.get_network_configuration.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_network_configuration.assert_called_once_with(42) - - def test_env_network_upload_json(self): - args = 'env network upload --format json -d /tmp 42' - config = {'foo': 'bar'} - expected_path = '/tmp/environment_42/network.json' - - m_open = mock.mock_open(read_data=json.dumps(config)) - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.set_network_configuration.assert_called_once_with(42, - config) - - @mock.patch('yaml.safe_dump') - def test_env_network_download_yaml(self, m_safe_dump): - args = 'env network download --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/environment_42/network.yaml' - - self.m_client.get_network_configuration.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_network_configuration.assert_called_once_with(42) - - def test_env_network_upload_yaml(self): - args = 'env network upload --format yaml -d /tmp 42' - config = {'foo': 'bar'} - expected_path = '/tmp/environment_42/network.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(config)) - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.set_network_configuration.assert_called_once_with(42, - config) - - @mock.patch('json.dump') - def test_env_settings_download_json(self, m_dump): - args = 'env settings download --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/environment_42/settings.json' - - self.m_client.get_settings.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_settings.assert_called_once_with(42) - - def test_env_settings_upload_json(self): - args = 'env settings upload --format json -d /tmp 42' - config = {'foo': 'bar'} - expected_path = '/tmp/environment_42/settings.json' - - m_open = mock.mock_open(read_data=json.dumps(config)) - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.set_settings.assert_called_once_with(42, - config, - force=False) - - @mock.patch('yaml.safe_dump') - def test_env_settings_download_yaml(self, m_safe_dump): - args = 'env settings download --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/environment_42/settings.yaml' - - self.m_client.get_settings.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.get_settings.assert_called_once_with(42) - - def test_env_settings_upload_yaml(self): - args = 'env settings upload --format yaml -d /tmp 42' - config = {'foo': 'bar'} - expected_path = '/tmp/environment_42/settings.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(config)) - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.set_settings.assert_called_once_with(42, - config, - force=False) - - def test_env_settings_upload_force(self): - args = 'env settings upload --format yaml -d /tmp --force 42' - config = {'foo': 'bar'} - expected_path = '/tmp/environment_42/settings.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(config)) - with mock.patch('fuelclient.commands.environment.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.set_settings.assert_called_once_with(42, - config, - force=True) - - def test_env_deployment_facts_delete(self): - args = "env deployment-facts delete 42" - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.delete_facts.assert_called_once_with(42, 'deployment') - - def test_env_provisioning_facts_delete(self): - args = "env provisioning-facts delete 42" - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.delete_facts.assert_called_once_with(42, 'provisioning') - - @mock.patch('json.dump') - def _deployment_facts_download_json(self, m_dump, default=False): - command = 'get-default' if default else 'download' - args = ( - "env deployment-facts {}" - " --env 42 --dir /tmp --nodes 2 --format json --no-split" - .format(command) - ) - data = [{'uid': 2, 'name': 'node'}] - expected_path = '/tmp/deployment_42/2.json' - - self.m_client.download_facts.return_value = data - - m_open = mock.mock_open() - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.download_facts.assert_called_once_with( - 42, 'deployment', nodes=[2], default=default, split=False) - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(data[0], mock.ANY, indent=4) - - def test_env_deployment_facts_download_json(self): - self._deployment_facts_download_json(default=False) - - def test_env_deployment_facts_get_default_json(self): - self._deployment_facts_download_json(default=True) - - @mock.patch('yaml.safe_dump') - def _deployment_facts_download_yaml(self, m_safe_dump, default=False): - command = 'get-default' if default else 'download' - args = ( - "env deployment-facts {}" - " --env 42 --dir /tmp --nodes 2 --format yaml" - .format(command) - ) - data = [{'uid': 2, 'name': 'node'}] - expected_path = '/tmp/deployment_42/2.yaml' - - self.m_client.download_facts.return_value = data - - m_open = mock.mock_open() - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.download_facts.assert_called_once_with( - 42, 'deployment', nodes=[2], default=default, split=True) - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(data[0], mock.ANY, - default_flow_style=False) - - def test_env_deployment_facts_download_yaml(self): - self._deployment_facts_download_yaml(default=False) - - def test_env_deployment_facts_get_default_yaml(self): - self._deployment_facts_download_yaml(default=True) - - def test_env_deployment_facts_upload_json(self): - args = 'env deployment-facts upload --env 42 --dir /tmp --format json' - data = [{'uid': 2, 'name': 'node'}] - expected_path = '/tmp/deployment_42/2.json' - - m_open = mock.mock_open(read_data=json.dumps(data[0])) - with mock.patch('os.listdir', return_value=['2.json']): - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - m_open.assert_called_once_with(expected_path, 'r') - self.m_client.upload_facts.assert_called_once_with( - 42, 'deployment', data) - - def test_env_deployment_facts_upload_yaml(self): - args = 'env deployment-facts upload --env 42 --dir /tmp --format yaml' - data = [{'uid': 2, 'name': 'node'}] - expected_path = '/tmp/deployment_42/2.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(data[0])) - with mock.patch('os.listdir', return_value=['2.yaml']): - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - m_open.assert_called_once_with(expected_path, 'r') - self.m_client.upload_facts.assert_called_once_with( - 42, 'deployment', data) - - @mock.patch('json.dump') - def _provisioning_facts_download_json(self, m_dump, default=False): - command = 'get-default' if default else 'download' - args = "env provisioning-facts {}" \ - " --env 42 --dir /tmp --nodes 2 --format json".format(command) - data = { - 'engine': {'foo': 'bar'}, - 'nodes': [{'uid': 2, 'name': 'node-2'}] - } - expected_path_engine = '/tmp/provisioning_42/engine.json' - expected_path_node = '/tmp/provisioning_42/2.json' - - self.m_client.download_facts.return_value = data - - m_open = mock.mock_open() - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.download_facts.assert_called_once_with( - 42, 'provisioning', nodes=[2], default=default, split=True) - m_open.assert_any_call(expected_path_engine, 'w') - m_dump.assert_any_call(data['engine'], mock.ANY, indent=4) - m_open.assert_any_call(expected_path_node, 'w') - m_dump.assert_any_call(data['nodes'][0], mock.ANY, indent=4) - - def test_env_provisioning_facts_download_json(self): - self._provisioning_facts_download_json(default=False) - - def test_env_provisioning_facts_get_default_json(self): - self._provisioning_facts_download_json(default=True) - - @mock.patch('yaml.safe_dump') - def _provisioning_facts_download_yaml(self, m_dump, default=False): - command = 'get-default' if default else 'download' - args = "env provisioning-facts {}" \ - " --env 42 --dir /tmp --nodes 2 --format yaml".format(command) - data = { - 'engine': {'foo': 'bar'}, - 'nodes': [{'uid': 2, 'name': 'node-2'}] - } - expected_path_engine = '/tmp/provisioning_42/engine.yaml' - expected_path_node = '/tmp/provisioning_42/2.yaml' - - self.m_client.download_facts.return_value = data - - m_open = mock.mock_open() - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.download_facts.assert_called_once_with( - 42, 'provisioning', nodes=[2], default=default, split=True) - m_open.assert_any_call(expected_path_engine, 'w') - m_dump.assert_any_call(data['engine'], mock.ANY, - default_flow_style=False) - m_open.assert_any_call(expected_path_node, 'w') - m_dump.assert_any_call(data['nodes'][0], mock.ANY, - default_flow_style=False) - - def test_env_provisioning_facts_download_yaml(self): - self._provisioning_facts_download_yaml(default=False) - - def test_env_provisioning_facts_get_default_yaml(self): - self._provisioning_facts_download_yaml(default=True) - - def test_env_provisioning_facts_upload_json(self): - args = 'env provisioning-facts upload' \ - ' --env 42 --dir /tmp --format json' - expected_data = { - 'engine': {'foo': 'bar'}, - 'nodes': [{'foo': 'bar'}] - } - expected_path_engine = '/tmp/provisioning_42/engine.json' - expected_path_node = '/tmp/provisioning_42/2.json' - - m_open = mock.mock_open(read_data=json.dumps({'foo': 'bar'})) - with mock.patch('os.listdir', return_value=['engine.json', '2.json']): - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - with mock.patch('os.path.lexists', return_value=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - m_open.assert_any_call(expected_path_engine, 'r') - m_open.assert_any_call(expected_path_node, 'r') - self.m_client.upload_facts.assert_called_once_with( - 42, 'provisioning', expected_data) - - def test_env_provisioning_facts_upload_yaml(self): - args = 'env provisioning-facts upload' \ - ' --env 42 --dir /tmp --format yaml' - expected_data = { - 'engine': {'foo': 'bar'}, - 'nodes': [{'foo': 'bar'}] - } - expected_path_engine = '/tmp/provisioning_42/engine.yaml' - expected_path_node = '/tmp/provisioning_42/2.yaml' - - m_open = mock.mock_open(read_data=json.dumps({'foo': 'bar'})) - with mock.patch('os.listdir', return_value=['engine.yaml', '2.yaml']): - with mock.patch('fuelclient.common.data_utils.open', - m_open, create=True): - with mock.patch('os.path.lexists', return_value=True): - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - m_open.assert_any_call(expected_path_engine, 'r') - m_open.assert_any_call(expected_path_node, 'r') - self.m_client.upload_facts.assert_called_once_with( - 42, 'provisioning', expected_data) diff --git a/fuelclient/tests/unit/v2/cli/test_extension.py b/fuelclient/tests/unit/v2/cli/test_extension.py deleted file mode 100644 index 891b4d8f..00000000 --- a/fuelclient/tests/unit/v2/cli/test_extension.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests import utils - - -class TestExtensionCommand(test_engine.BaseCLITest): - """Tests for fuel2 extension * commands.""" - - def test_extensions_list(self): - self.m_client.get_all.return_value = utils.get_fake_extensions(2) - args = 'extension list' - self.exec_command(args) - self.m_client.get_all.assert_called_once_with() - self.m_get_client.assert_called_once_with('extension', mock.ANY) - - def test_env_extensions_show(self): - self.m_client.get_extensions.return_value = \ - utils.get_fake_env_extensions() - env_id = 45 - args = 'env extension show {id}'.format(id=env_id) - self.exec_command(args) - self.m_client.get_by_id.assert_called_once_with(env_id) - self.m_get_client.assert_called_once_with('extension', mock.ANY) - - @mock.patch('sys.stderr') - def test_env_extension_show_fail(self, mocked_stderr): - args = 'env extension show' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('id', - mocked_stderr.write.call_args_list[0][0][0]) - - @mock.patch('sys.stderr') - def test_env_extension_enable_fail(self, mocked_stderr): - args = 'env extension enable 1' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-E/--extensions', - mocked_stderr.write.call_args_list[-1][0][0]) - - @mock.patch('sys.stderr') - def test_env_extension_disable_fail(self, mocked_stderr): - args = 'env extension disable 1' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-E/--extensions', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_env_extensions_enable(self): - exts = utils.get_fake_env_extensions() - env_id = 45 - args = 'env extension enable {id} --extensions {exts}'.format( - id=env_id, exts=' '.join(exts)) - self.exec_command(args) - self.m_client.enable_extensions.assert_called_once_with(env_id, exts) - self.m_get_client.assert_called_once_with('extension', mock.ANY) - - def test_env_extensions_disable(self): - exts = utils.get_fake_env_extensions() - env_id = 45 - args = 'env extension disable {id} --extensions {exts}'.format( - id=env_id, exts=' '.join(exts)) - self.exec_command(args) - self.m_client.disable_extensions.assert_called_once_with(env_id, exts) - self.m_get_client.assert_called_once_with('extension', mock.ANY) diff --git a/fuelclient/tests/unit/v2/cli/test_fuel_version.py b/fuelclient/tests/unit/v2/cli/test_fuel_version.py deleted file mode 100644 index eb110e89..00000000 --- a/fuelclient/tests/unit/v2/cli/test_fuel_version.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 json -import mock -from six import moves -import yaml - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_fuel_version - - -class TestFuelVersionCommand(test_engine.BaseCLITest): - """Tests for fuel2 version * commands.""" - - def setUp(self): - super(TestFuelVersionCommand, self).setUp() - self.m_client.get_all.return_value = \ - fake_fuel_version.get_fake_fuel_version() - - def test_fuel_version_yaml(self): - args = 'fuel-version -f yaml' - - with mock.patch('sys.stdout', new=moves.cStringIO()) as m_stdout: - self.exec_command(args) - self.assertEqual(fake_fuel_version.get_fake_fuel_version(), - yaml.safe_load(m_stdout.getvalue())) - - def test_fuel_version_json(self): - args = 'fuel-version -f json' - - with mock.patch('sys.stdout', new=moves.cStringIO()) as m_stdout: - self.exec_command(args) - self.assertEqual(fake_fuel_version.get_fake_fuel_version(), - json.loads(m_stdout.getvalue())) diff --git a/fuelclient/tests/unit/v2/cli/test_health.py b/fuelclient/tests/unit/v2/cli/test_health.py deleted file mode 100644 index 346b96c5..00000000 --- a/fuelclient/tests/unit/v2/cli/test_health.py +++ /dev/null @@ -1,169 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_health - - -class TestHealthCommand(test_engine.BaseCLITest): - """Tests for fuel2 health * commands.""" - - def test_health_list_for_cluster(self): - self.m_client.get_all.return_value = fake_health.get_fake_test_sets(10) - cluster_id = 45 - args = 'health list -e {id}'.format(id=cluster_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with( - environment_id=cluster_id) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - @mock.patch('sys.stderr') - def test_health_list_for_cluster_fail(self, mocked_stderr): - args = 'health list' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_health_status_list(self): - self.m_client.get_status_all.return_value = [ - fake_health.get_fake_test_set_item(testset_id=12, cluster_id=30), - fake_health.get_fake_test_set_item(testset_id=13, cluster_id=32), - fake_health.get_fake_test_set_item(testset_id=14, cluster_id=35) - ] - args = 'health status list' - self.exec_command(args) - self.m_client.get_status_all.assert_called_once_with(None) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - def test_health_status_list_for_cluster(self): - cluster_id = 45 - self.m_client.get_status_all.return_value = [ - fake_health.get_fake_test_set_item(testset_id=12, - cluster_id=cluster_id), - fake_health.get_fake_test_set_item(testset_id=13, - cluster_id=cluster_id), - fake_health.get_fake_test_set_item(testset_id=14, - cluster_id=cluster_id) - ] - args = 'health status list -e {id}'.format(id=cluster_id) - self.exec_command(args) - self.m_client.get_status_all.assert_called_once_with(cluster_id) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - def test_health_status_show(self): - testset_id = 66 - self.m_client.get_status_single.return_value = \ - fake_health.get_fake_test_set_item(testset_id=testset_id) - args = 'health status show {id}'.format(id=testset_id) - self.exec_command(args) - self.m_client.get_status_single.assert_called_once_with(testset_id) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - @mock.patch('sys.stderr') - def test_health_status_show_fail(self, mocked_stderr): - args = 'health status show' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('id', mocked_stderr.write.call_args_list[0][0][0]) - - def test_health_start_force(self): - cluster_id = 45 - testset = ['fake_test_set1', 'fake_test_set2'] - args = 'health start -e {id} -t {testset} --force'.format( - id=cluster_id, testset=' '.join(testset)) - self.exec_command(args) - self.m_client.start.assert_called_once_with(cluster_id, - ostf_credentials={}, - test_sets=testset, - force=True) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - @mock.patch('sys.stderr') - def test_health_start_w_wrong_parameters(self, mocked_stderr): - args = 'health start' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_health_start_wo_force(self): - cluster_id = 45 - testset = ['fake_test_set1', 'fake_test_set2'] - args = 'health start -e {id} -t {testset}'.format( - id=cluster_id, testset=' '.join(testset)) - self.exec_command(args) - self.m_client.start.assert_called_once_with(cluster_id, - ostf_credentials={}, - test_sets=testset, - force=False) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - def test_health_start_all_wo_force(self): - cluster_id = 45 - args = 'health start -e {id}'.format(id=cluster_id) - self.exec_command(args) - self.m_client.start.assert_called_once_with(cluster_id, - ostf_credentials={}, - test_sets=None, - force=False) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - def test_health_start_force_w_ostf_credentials(self): - cluster_id = 45 - testset = ['fake_test_set1', 'fake_test_set2'] - ostf_credentials = {'username': 'fake_user', - 'password': 'fake_password', - 'tenant': 'fake_tenant_name'} - - args = ('health start -e {id} -t {testset} --force --ostf-username ' - 'fake_user --ostf-password fake_password --ostf-tenant-name ' - 'fake_tenant_name'.format(id=cluster_id, - testset=' '.join(testset))) - - self.exec_command(args) - self.m_client.start.assert_called_once_with( - cluster_id, - ostf_credentials=ostf_credentials, - test_sets=testset, - force=True - ) - self.m_get_client.assert_called_once_with('health', mock.ANY) - - def test_health_stop(self): - testset_id = 66 - args = 'health stop {id}'.format(id=testset_id) - self.exec_command(args) - self.m_client.action.assert_called_once_with(testset_id, 'stopped') - self.m_get_client.assert_called_once_with('health', mock.ANY) - - @mock.patch('sys.stderr') - def test_health_stop_fail(self, mocked_stderr): - args = 'health stop' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('id', mocked_stderr.write.call_args_list[0][0][0]) - - def test_health_restart(self): - testset_id = 66 - args = 'health restart {id}'.format(id=testset_id) - self.exec_command(args) - self.m_client.action.assert_called_once_with(testset_id, 'restarted') - self.m_get_client.assert_called_once_with('health', mock.ANY) - - @mock.patch('sys.stderr') - def test_health_restart_fail(self, mocked_stderr): - args = 'health restart' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('id', mocked_stderr.write.call_args_list[0][0][0]) diff --git a/fuelclient/tests/unit/v2/cli/test_network_group.py b/fuelclient/tests/unit/v2/cli/test_network_group.py deleted file mode 100644 index 8fbaed20..00000000 --- a/fuelclient/tests/unit/v2/cli/test_network_group.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 json -import mock - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_network_group -from fuelclient.v1.network_group import NetworkGroupClient - - -class TestNetworkGroupCommand(test_engine.BaseCLITest): - - def setUp(self): - super(TestNetworkGroupCommand, self).setUp() - - get_fake_ng = fake_network_group.get_fake_network_group - - self.m_client.get_all.return_value = [ - get_fake_ng() for _ in range(10)] - self.m_client.get_by_id.return_value = get_fake_ng() - self.m_client.create.return_value = get_fake_ng() - - def test_network_group_list(self): - args = 'network-group list' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('network-group', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_network_group_show(self): - args = 'network-group show 1' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('network-group', mock.ANY) - self.m_client.get_by_id.assert_called_once_with(1) - - def test_network_group_create(self): - meta = {'notation': 'cidr'} - meta_str = json.dumps(meta).replace(r'"', r'\"') - - args = 'network-group create -N 8 -C 10.10.0.0/24 -g 10.10.0.1' \ - ' -V 16 -r 32 testng --meta "{0}"'.format(meta_str) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('network-group', mock.ANY) - - m_client = self.m_client - m_client.create.assert_called_once_with( - name='testng', group_id=8, cidr='10.10.0.0/24', vlan=16, - release=32, gateway='10.10.0.1', meta=meta) - - def test_network_group_update(self): - self.m_client.updatable_attributes = \ - NetworkGroupClient.updatable_attributes - - meta = {'notation': 'cidr'} - meta_str = json.dumps(meta).replace(r'"', r'\"') - - args = 'network-group update -C 10.10.0.0/24' \ - ' --meta "{0}" 1'.format(meta_str) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('network-group', mock.ANY) - - m_client = self.m_client - m_client.update.assert_called_once_with( - 1, cidr='10.10.0.0/24', meta=meta) - - def test_network_group_delete(self): - args = 'network-group delete 42' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('network-group', mock.ANY) - self.m_client.delete_by_id.assert_called_once_with(42) diff --git a/fuelclient/tests/unit/v2/cli/test_network_template.py b/fuelclient/tests/unit/v2/cli/test_network_template.py deleted file mode 100644 index 4838a032..00000000 --- a/fuelclient/tests/unit/v2/cli/test_network_template.py +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright 2015 Mirantis, 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine - - -class TestNetworkTemplateCommand(test_engine.BaseCLITest): - - @mock.patch('sys.stderr') - def test_network_template_upload_fail(self, mocked_stderr): - args = 'network-template upload 1' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('--file', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_network_template_upload_w_file(self): - args = 'network-template upload --file /tmp/test-file 1' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - self.m_client.upload_network_template.assert_called_once_with( - 1, '/tmp/test-file') - - def test_network_template_download(self): - download_mock = self.m_client.download_network_template - download_mock.return_value = '/tmp/test-dir/settings_1' - - args = 'network-template download 1' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - download_mock.assert_called_once_with(1, None) - - def test_network_template_download_w_dir(self): - download_mock = self.m_client.download_network_template - download_mock.return_value = '/tmp/test-dir/settings_1' - - args = 'network-template download --dir /tmp/test-dir 1' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - download_mock.assert_called_once_with(1, '/tmp/test-dir') - - def test_network_template_delete(self): - args = 'network-template delete 1' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('environment', mock.ANY) - delete_mock = self.m_client.delete_network_template - delete_mock.assert_called_once_with(1) diff --git a/fuelclient/tests/unit/v2/cli/test_node.py b/fuelclient/tests/unit/v2/cli/test_node.py deleted file mode 100644 index 37c4bb7d..00000000 --- a/fuelclient/tests/unit/v2/cli/test_node.py +++ /dev/null @@ -1,625 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 json - -import mock -import six -import yaml - -from six import StringIO - -from fuelclient.commands import node as cmd_node -from fuelclient import main as main_mod -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_node -from fuelclient.v1 import node - - -class TestNodeCommand(test_engine.BaseCLITest): - """Tests for fuel2 node * commands.""" - - def setUp(self): - super(TestNodeCommand, self).setUp() - - self.m_client.get_all.return_value = [fake_node.get_fake_node() - for i in range(10)] - self.m_client.get_by_id.return_value = fake_node.get_fake_node() - - def test_node_list(self): - args = 'node list' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_node_list_sorted(self): - args = 'node list -s name' - self.exec_command(args) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_node_list_with_env(self): - env_id = 42 - args = 'node list --env {env}'.format(env=env_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all.assert_called_once_with( - environment_id=env_id) - - def test_node_list_with_labels(self): - labels = ['key_1=val_1', 'key_2=val_2', 'key3'] - args = 'node list --labels {labels}'.format( - labels=' '.join(labels)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all.assert_called_once_with(labels=labels) - - def test_node_list_with_env_and_labels(self): - env_id = 42 - labels = ['key_1=val_1', 'key_2=val_2', 'key3'] - args = 'node list --env {env} --labels {labels}'.format( - env=env_id, labels=' '.join(labels)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all.assert_called_once_with( - environment_id=env_id, labels=labels) - self.assertIsInstance( - self.m_client.get_all.call_args[1].get('labels')[0], six.text_type) - - def test_node_list_ansible_inventory(self): - self.m_client.get_all.return_value = [ - fake_node.get_fake_node(hostname='node-1', - ip='10.20.0.2', - roles=['compute']), - fake_node.get_fake_node(hostname='node-2', - ip='10.20.0.3', - roles=['compute', 'ceph-osd']), - fake_node.get_fake_node(hostname='node-3', - ip='10.20.0.4', - roles=['controller']), - fake_node.get_fake_node(hostname='node-4', - ip='10.20.0.5', - roles=['controller', 'mongo']), - fake_node.get_fake_node(hostname='node-5', - ip='10.20.0.6', - roles=['controller', 'ceph-osd']), - ] - - expected_output = '''\ -[ceph-osd] -node-2 ansible_host=10.20.0.3 -node-5 ansible_host=10.20.0.6 - -[compute] -node-1 ansible_host=10.20.0.2 -node-2 ansible_host=10.20.0.3 - -[controller] -node-3 ansible_host=10.20.0.4 -node-4 ansible_host=10.20.0.5 -node-5 ansible_host=10.20.0.6 - -[mongo] -node-4 ansible_host=10.20.0.5 - -''' - - args = 'node ansible-inventory --env 1' - with mock.patch('sys.stdout', new=StringIO()) as mstdout: - rv = self.exec_command(args) - actual_output = mstdout.getvalue() - - self.assertFalse(rv) - self.assertEqual(expected_output, actual_output) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all.assert_called_once_with( - environment_id=1, labels=None) - - def test_node_show(self): - node_id = 42 - args = 'node show {node_id}'.format(node_id=node_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_by_id.assert_called_once_with(node_id) - - def test_node_vms_conf_list(self): - node_id = 42 - args = 'node list-vms-conf {node_id}'.format(node_id=node_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_node_vms_conf.assert_called_once_with(node_id) - - def test_node_vms_conf_create(self): - vms_conf = r'{\"id\":2} {\"id\":3}' - config = [{'id': 2}, - {'id': 3}] - - node_id = 42 - - args = 'node create-vms-conf {0} --conf {1}'.format( - node_id, - vms_conf) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.node_vms_create.assert_called_once_with(node_id, config) - - def test_node_vms_conf_create_from_list(self): - vms_conf = '[{"id": 2}, {"id": 3}]' - config = [{'id': 2}, {'id': 3}] - - node_id = 42 - - args = "node create-vms-conf {0} --conf '{1}'".format( - node_id, vms_conf) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.node_vms_create.assert_called_once_with(node_id, config) - - def test_node_vms_conf_create_fail(self): - vms_conf = '[{"id": ' - node_id = 42 - - args = "node create-vms-conf {0} --conf '{1}'".format(node_id, - vms_conf) - self.assertRaises(SystemExit, - self.exec_command, - args) - - @mock.patch('cliff.formatters.table.TableFormatter.emit_one') - def test_node_set_hostname(self, m_emit_one): - self.m_client._updatable_attributes = \ - node.NodeClient._updatable_attributes - node_id = 42 - hostname = 'test-name' - expected_field_data = cmd_node.NodeShow.columns - - self.m_client.update.return_value = \ - fake_node.get_fake_node(node_id=node_id, - hostname=hostname) - - args = 'node update {node_id} --hostname {hostname}'\ - .format(node_id=node_id, hostname=hostname) - - self.exec_command(args) - m_emit_one.assert_called_once_with(expected_field_data, - mock.ANY, - mock.ANY, - mock.ANY) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.update.assert_called_once_with( - node_id, hostname=hostname) - - @mock.patch('cliff.formatters.table.TableFormatter.emit_one') - def test_node_set_name(self, m_emit_one): - self.m_client._updatable_attributes = \ - node.NodeClient._updatable_attributes - node_id = 37 - expected_field_data = cmd_node.NodeShow.columns - - test_cases = ('new-name', 'New Name', 'śćż∑ Pó', '你一定是无聊') - for name in test_cases: - self.m_client.update.return_value = fake_node.get_fake_node( - node_id=node_id, node_name=name) - - cmd = ['node', 'update', str(node_id), '--name', name] - - # NOTE(sbrzeczkowski): due to shlex inability to accept - # unicode arguments prior to python 2.7.3 - main_mod.main(argv=cmd) - - if six.PY2: - name = name.decode('utf-8') - - m_emit_one.assert_called_with(expected_field_data, - mock.ANY, - mock.ANY, - mock.ANY) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.update.assert_called_once_with( - node_id, name=name) - self.m_get_client.reset_mock() - self.m_client.reset_mock() - - def test_node_label_list_for_all_nodes(self): - args = 'node label list' - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all_labels_for_nodes.assert_called_once_with( - node_ids=None) - - def test_node_label_list_sorted(self): - args = 'node label list -s label_name' - self.exec_command(args) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all_labels_for_nodes.assert_called_once_with( - node_ids=None) - - def test_node_label_list_for_specific_nodes(self): - node_ids = ['42', '43'] - args = 'node label list --nodes {node_ids}'.format( - node_ids=' '.join(node_ids)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_all_labels_for_nodes.assert_called_once_with( - node_ids=node_ids) - - def test_node_label_set_for_all_nodes(self): - labels = ['key_1=val_1', 'key_2=val_2'] - args = 'node label set -l {labels} --nodes-all'.format( - labels=' '.join(labels)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.set_labels_for_nodes.assert_called_once_with( - labels=labels, node_ids=None) - - @mock.patch('argparse.ArgumentParser.error') - def test_node_label_set_for_all_nodes_wo_labels_arg(self, merror): - cmd = 'node label set --nodes-all' - self.exec_command(cmd) - args, _ = merror.call_args - self.assertIn('-l/--labels', args[0]) - - def test_node_label_set_for_specific_nodes(self): - labels = ['key_1=val_1', 'key_2=val_2'] - node_ids = ['42', '43'] - args = 'node label set -l {labels} --nodes {node_ids}'.format( - labels=' '.join(labels), node_ids=' '.join(node_ids)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.set_labels_for_nodes.assert_called_once_with( - labels=labels, node_ids=node_ids) - - def test_node_delete_specific_labels_for_all_nodes(self): - labels = ['key_1', 'key_2'] - args = 'node label delete -l {labels} --nodes-all'.format( - labels=' '.join(labels)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.delete_labels_for_nodes.assert_called_once_with( - labels=labels, node_ids=None) - - @mock.patch('json.dump') - def test_node_disks_download_json(self, m_dump): - args = 'node disks download --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/disks.json' - - self.m_client.get_disks.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_disks.assert_called_once_with(42) - - def test_node_disks_upload_json(self): - args = 'node disks upload --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/disks.json' - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.set_disks.assert_called_once_with(42, test_data) - - @mock.patch('json.dump') - def test_node_disks_getdefault_json(self, m_dump): - args = 'node disks get-default --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/disks.json' - - self.m_client.get_default_disks.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_default_disks.assert_called_once_with(42) - - @mock.patch('yaml.safe_dump') - def test_node_disks_download_yaml(self, m_safe_dump): - args = 'node disks download --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/disks.yaml' - - self.m_client.get_disks.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_disks.assert_called_once_with(42) - - def test_node_disks_upload_yaml(self): - args = 'node disks upload --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/disks.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(test_data)) - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.set_disks.assert_called_once_with(42, test_data) - - @mock.patch('yaml.safe_dump') - def test_node_disks_getdefault_yaml(self, m_safe_dump): - args = 'node disks get-default --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/disks.yaml' - - self.m_client.get_default_disks.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_default_disks.assert_called_once_with(42) - - def test_node_delete_specific_labels_for_specific_nodes(self): - labels_keys = ['key_1', 'key_2'] - node_ids = ['42', '43'] - args = 'node label delete -l {labels} --nodes {node_ids}'.format( - labels=' '.join(labels_keys), node_ids=' '.join(node_ids)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.delete_labels_for_nodes.assert_called_once_with( - labels=labels_keys, node_ids=node_ids) - - def test_node_delete_all_labels_for_all_nodes(self): - args = 'node label delete --labels-all --nodes-all' - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.delete_labels_for_nodes.assert_called_once_with( - labels=None, node_ids=None) - - def test_node_delete_all_labels_for_specific_nodes(self): - node_ids = ['42', '43'] - args = 'node label delete --labels-all --nodes {node_ids}'.format( - node_ids=' '.join(node_ids)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.delete_labels_for_nodes.assert_called_once_with( - labels=None, node_ids=node_ids) - - def test_node_label_delete_by_value(self): - labels = ['key_1', 'key_2=value2'] - node_ids = ['42', '43'] - args = 'node label delete -l {labels} --nodes {node_ids}'.format( - labels=' '.join(labels), node_ids=' '.join(node_ids)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.delete_labels_for_nodes.assert_called_once_with( - labels=labels, node_ids=node_ids) - - def test_node_label_delete_by_value_with_whitespace(self): - labels = ['key_1', "'key_2 =value2'"] - labels_expected = [x.strip("'") for x in labels] - node_ids = ['42', '43'] - args = 'node label delete -l {labels} --nodes {node_ids}'.format( - labels=' '.join(labels), node_ids=' '.join(node_ids)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.delete_labels_for_nodes.assert_called_once_with( - labels=labels_expected, node_ids=node_ids) - - def test_node_attributes_download(self): - args = 'node attributes-download 42' - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.download_attributes.assert_called_once_with(42, None) - - def test_node_attributes_upload(self): - args = 'node attributes-upload 42' - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.upload_attributes.assert_called_once_with(42, None) - - @mock.patch('json.dump') - def test_node_interfaces_download_json(self, m_dump): - args = 'node interfaces download --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/interfaces.json' - - self.m_client.get_interfaces.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_interfaces.assert_called_once_with(42) - - def test_node_interfaces_upload_json(self): - args = 'node interfaces upload --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/interfaces.json' - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.set_interfaces.assert_called_once_with(42, test_data) - - @mock.patch('json.dump') - def test_node_interfaces_getdefault_json(self, m_dump): - args = 'node interfaces get-default --format json -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/interfaces.json' - - self.m_client.get_default_interfaces.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_default_interfaces.assert_called_once_with(42) - - @mock.patch('yaml.safe_dump') - def test_node_interfaces_download_yaml(self, m_safe_dump): - args = 'node interfaces download --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/interfaces.yaml' - - self.m_client.get_interfaces.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_interfaces.assert_called_once_with(42) - - def test_node_interfaces_upload_yaml(self): - args = 'node interfaces upload --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/interfaces.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(test_data)) - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.set_interfaces.assert_called_once_with(42, test_data) - - @mock.patch('yaml.safe_dump') - def test_node_interfaces_getdefault_yaml(self, m_safe_dump): - args = 'node interfaces get-default --format yaml -d /tmp 42' - test_data = {'foo': 'bar'} - expected_path = '/tmp/node_42/interfaces.yaml' - - self.m_client.get_default_interfaces.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.node.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.get_default_interfaces.assert_called_once_with(42) - - def test_undiscover_nodes_by_id(self): - args = 'node undiscover -n 24' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.undiscover_nodes.assert_called_once_with( - env_id=None, node_id=24, force=False) - - def test_undiscover_nodes_by_id_force(self): - args = 'node undiscover -n 24 --force' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.undiscover_nodes.assert_called_once_with( - env_id=None, node_id=24, force=True) - - def test_undiscover_nodes_by_cluster_id(self): - args = 'node undiscover -e 45' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.undiscover_nodes.assert_called_once_with( - env_id=45, node_id=None, force=False) - - def test_undiscover_nodes_by_cluster_id_force(self): - args = 'node undiscover -e 45 --force' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('node', mock.ANY) - self.m_client.undiscover_nodes.assert_called_once_with( - env_id=45, node_id=None, force=True) - - @mock.patch('sys.stderr') - def test_undiscover_nodes_w_wrong_params(self, mocked_stderr): - args = 'node undiscover -e 45 -n 24' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('argument -n/--node: not allowed with argument -e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) diff --git a/fuelclient/tests/unit/v2/cli/test_openstack_config.py b/fuelclient/tests/unit/v2/cli/test_openstack_config.py deleted file mode 100644 index 4b91abc8..00000000 --- a/fuelclient/tests/unit/v2/cli/test_openstack_config.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright 2015 Mirantis, 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests import utils - - -class TestOpenstackConfig(test_engine.BaseCLITest): - CLUSTER_ID = 42 - NODE_ID = 64 - - def _test_config_list(self, cmd_line, expected_kwargs): - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - self.exec_command('openstack-config list {0}'.format(cmd_line)) - self.m_get_client.assert_called_once_with('openstack-config', - mock.ANY) - self.m_client.get_filtered.assert_called_once_with( - **expected_kwargs) - - def test_config_list_for_node(self): - self._test_config_list( - cmd_line='--env {0} --node {1}'.format(self.CLUSTER_ID, - self.NODE_ID), - expected_kwargs={'cluster_id': self.CLUSTER_ID, - 'node_ids': [self.NODE_ID], 'node_role': None, - 'is_active': True} - ) - - def test_config_list_for_role(self): - self._test_config_list( - cmd_line='--env {0} --role compute'.format(self.CLUSTER_ID), - expected_kwargs={'cluster_id': self.CLUSTER_ID, 'node_ids': None, - 'node_role': 'compute', 'is_active': True} - ) - - def test_config_list_for_cluster(self): - self._test_config_list( - cmd_line='--env {0}'.format(self.CLUSTER_ID), - expected_kwargs={'cluster_id': self.CLUSTER_ID, 'node_ids': None, - 'node_role': None, 'is_active': True} - ) - - def test_config_list_sorted(self): - self._test_config_list( - cmd_line='--env {0} -s node_id'.format(self.CLUSTER_ID), - expected_kwargs={'cluster_id': self.CLUSTER_ID, 'node_ids': None, - 'node_role': None, 'is_active': True} - ) - - @mock.patch('sys.stderr') - def test_config_list_for_cluster_fail(self, mocked_stderr): - self.assertRaises(SystemExit, - self.exec_command, 'openstack-config list') - self.assertIn('-e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_config_upload(self): - self.m_client.upload.return_value = [utils.get_fake_openstack_config() - for i in range(10)] - - cmd = 'openstack-config upload --env {0} --node {1} --file ' \ - 'config.yaml'.format(self.CLUSTER_ID, self.NODE_ID) - self.exec_command(cmd) - - self.m_get_client.assert_called_once_with('openstack-config', mock.ANY) - self.m_client.upload.assert_called_once_with( - path='config.yaml', cluster_id=self.CLUSTER_ID, - node_ids=[self.NODE_ID], node_role=None) - - @mock.patch('sys.stderr') - def test_config_upload_fail(self, mocked_stderr): - cmd = 'openstack-config upload --env {0} ' \ - '--node {1}'.format(self.CLUSTER_ID, self.NODE_ID) - self.assertRaises(SystemExit, self.exec_command, cmd) - self.assertIn('--file', - mocked_stderr.write.call_args_list[-1][0][0]) - mocked_stderr.reset_mock() - - cmd = 'openstack-config upload --node {1} ' \ - '--file config.yaml'.format(self.CLUSTER_ID, self.NODE_ID) - self.assertRaises(SystemExit, self.exec_command, cmd) - self.assertIn('-e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_config_download(self): - self.m_client.download.return_value = 'config.yaml' - - cmd = 'openstack-config download 1 --file config.yaml' - self.exec_command(cmd) - - self.m_get_client.assert_called_once_with('openstack-config', mock.ANY) - self.m_client.download.assert_called_once_with(1, 'config.yaml') - - @mock.patch('sys.stderr') - def test_config_download_fail(self, mocked_stderr): - cmd = 'openstack-config download 1' - self.assertRaises(SystemExit, self.exec_command, cmd) - self.assertIn('--file', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_config_execute(self): - cmd = 'openstack-config execute --env {0} --node {1}' \ - ''.format(self.CLUSTER_ID, self.NODE_ID) - self.exec_command(cmd) - - self.m_get_client.assert_called_once_with('openstack-config', mock.ANY) - self.m_client.execute.assert_called_once_with( - cluster_id=self.CLUSTER_ID, node_ids=[self.NODE_ID], - node_role=None, force=False) - - def test_config_force_execute(self): - task_id = 42 - test_task = utils.get_fake_task(task_id=task_id) - - self.m_client.execute.return_value = test_task - - cmd = ('openstack-config execute --env {0}' - ' --node {1} --force ').format(self.CLUSTER_ID, self.NODE_ID) - - self.exec_command(cmd) - - self.m_get_client.assert_called_once_with('openstack-config', mock.ANY) - self.m_client.execute.assert_called_once_with( - cluster_id=self.CLUSTER_ID, node_ids=[self.NODE_ID], - node_role=None, force=True) - - def test_config_delete(self): - cmd = 'openstack-config delete 1' - self.exec_command(cmd) - - self.m_get_client.assert_called_once_with('openstack-config', mock.ANY) - self.m_client.delete.assert_called_once_with(1) diff --git a/fuelclient/tests/unit/v2/cli/test_plugins.py b/fuelclient/tests/unit/v2/cli/test_plugins.py deleted file mode 100644 index 95bf9e3c..00000000 --- a/fuelclient/tests/unit/v2/cli/test_plugins.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 mock -import tempfile - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_plugin - - -class TestPluginsCommand(test_engine.BaseCLITest): - """Tests for fuel2 plugins * commands.""" - - def setUp(self): - super(TestPluginsCommand, self).setUp() - self.name = 'fuel_plugin' - self.version = '1.0.0' - - get_fake_plugins = fake_plugin.get_fake_plugins - - self.m_client.get_modified.return_value = get_fake_plugins(10) - - def test_plugin_list(self): - args = 'plugins list' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('plugins', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_plugin_list_sorted(self): - args = 'plugins list -s name' - self.exec_command(args) - self.m_get_client.assert_called_once_with('plugins', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_plugins_sync_all(self): - args = 'plugins sync' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('plugins', mock.ANY) - self.m_client.sync.assert_called_once_with(ids=None) - - def test_plugins_sync_specified_plugins(self): - ids = [1, 2] - args = 'plugins sync {ids}'.format(ids=' '.join(map(str, ids))) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('plugins', mock.ANY) - self.m_client.sync.assert_called_once_with(ids=ids) - - def exec_install(self, ext='rpm', force=False): - path = tempfile.mkstemp(suffix='.{}'.format(ext))[1] - args = 'plugins install {0} {1}'.format(path, - '--force' if force else '') - self.exec_command(args) - - self.m_get_client.assert_called_once_with('plugins', mock.ANY) - self.m_client.install.assert_called_once_with(path, force=force) - - def test_plugin_install(self): - self.exec_install() - - def test_plugin_install_with_force(self): - self.exec_install(force=True) - - def test_plugin_remove(self): - args = 'plugins remove {0} {1}'.format(self.name, self.version) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('plugins', mock.ANY) - self.m_client.remove.assert_called_once_with(self.name, self.version) diff --git a/fuelclient/tests/unit/v2/cli/test_release.py b/fuelclient/tests/unit/v2/cli/test_release.py deleted file mode 100644 index 6d397bcd..00000000 --- a/fuelclient/tests/unit/v2/cli/test_release.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_release - - -class TestReleaseCommand(test_engine.BaseCLITest): - """Tests for fuel2 release * commands.""" - - def setUp(self): - super(TestReleaseCommand, self).setUp() - self.m_client.get_by_id.return_value = fake_release.get_fake_release() - self.m_client.get_attributes_metadata_by_id.return_value = \ - fake_release.get_fake_attributes_metadata() - self.m_client.get_components_by_id.return_value = \ - fake_release.get_fake_release_components(10) - - def test_release_list(self): - args = 'release list' - self.exec_command(args) - self.m_client.get_all.assert_called_once_with() - self.m_get_client.assert_called_once_with('release', mock.ANY) - - def test_release_repos_list(self): - args = 'release repos list 1' - self.exec_command(args) - self.m_client.get_attributes_metadata_by_id.assert_called_once_with(1) - self.m_get_client.assert_called_once_with('release', mock.ANY) - - def test_release_repos_list_sorted(self): - args = 'release repos list 1 -s name' - self.exec_command(args) - self.m_client.get_attributes_metadata_by_id.assert_called_once_with(1) - self.m_get_client.assert_called_once_with('release', mock.ANY) - - @mock.patch('fuelclient.commands.release.utils.parse_yaml_file') - def test_release_repos_update(self, mock_parse_yaml): - args = 'release repos update 1 -f repos.yaml' - new_repos = [ - { - "name": "fake", - "type": "deb", - "uri": "some_uri", - "priority": 1050, - "section": "main", - "suite": "trusty" - } - ] - mock_parse_yaml.return_value = new_repos - data = fake_release.get_fake_attributes_metadata() - data["editable"]["repo_setup"]["repos"]["value"] = new_repos - self.exec_command(args) - mock_parse_yaml.assert_called_once_with('repos.yaml') - self.m_client.get_attributes_metadata_by_id.assert_called_once_with(1) - self.m_client.update_attributes_metadata_by_id \ - .assert_called_once_with(1, data) - self.m_get_client.assert_called_once_with('release', mock.ANY) - - def test_release_component_list(self): - release_id = 42 - args = 'release component list {0}'.format(release_id) - self.exec_command(args) - self.m_client.get_components_by_id.assert_called_once_with(release_id) - self.m_get_client.assert_called_once_with('release', mock.ANY) - - def test_release_component_list_sorted(self): - release_id = 42 - args = 'release component list {0} -s default'.format(release_id) - self.exec_command(args) - self.m_client.get_components_by_id.assert_called_once_with(release_id) - self.m_get_client.assert_called_once_with('release', mock.ANY) diff --git a/fuelclient/tests/unit/v2/cli/test_role.py b/fuelclient/tests/unit/v2/cli/test_role.py deleted file mode 100644 index d54f8c38..00000000 --- a/fuelclient/tests/unit/v2/cli/test_role.py +++ /dev/null @@ -1,359 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 json -import mock -import yaml - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_role - - -class TestRoleCommand(test_engine.BaseCLITest): - """Tests for fuel2 role * commands.""" - - def test_role_list_for_release(self): - self.m_client.get_all.return_value = [ - {"name": "fake_role_1", - "group": "fake_group", - "conflicts": ["fake_role_2", "fake_role_3"], - "description": "some fake description"}, - {"name": "fake_role_2", - "group": "fake_group", - "conflicts": ["fake_role_1", "fake_role_3"], - "description": "some fake description"} - ] - release_id = 45 - args = 'role list -r {id}'.format(id=release_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with('releases', release_id) - self.m_get_client.assert_called_once_with('role', mock.ANY) - - def test_role_list_for_cluster(self): - self.m_client.get_all.return_value = [ - {"name": "fake_role_1", - "group": "fake_group", - "conflicts": ["fake_role_2", "fake_role_3"], - "description": "some fake description"}, - {"name": "fake_role_2", - "group": "fake_group", - "conflicts": ["fake_role_1", "fake_role_3"], - "description": "some fake description"} - ] - env_id = 45 - args = 'role list -e {id}'.format(id=env_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with('clusters', env_id) - self.m_get_client.assert_called_once_with('role', mock.ANY) - - def test_role_list_sorted(self): - self.m_client.get_all.return_value = [ - {"name": "fake_role_2", - "group": "fake_group_1", - "conflicts": ["fake_role_1", "fake_role_3"], - "description": "some fake description"}, - {"name": "fake_role_1", - "group": "fake_group_2", - "conflicts": ["fake_role_2", "fake_role_3"], - "description": "some fake description"}, - ] - env_id = 45 - args = 'role list -e {id} -s group'.format(id=env_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with('clusters', env_id) - self.m_get_client.assert_called_once_with('role', mock.ANY) - - @mock.patch('sys.stderr') - def test_role_list_fail(self, mocked_stderr): - args = 'role list' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-r/--release -e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) - - @mock.patch('sys.stderr') - def test_role_list_with_mutually_exclusive_params(self, mocked_stderr): - args = 'role list -e 1 -r 2' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('not allowed', - mocked_stderr.write.call_args_list[-1][0][0]) - - @mock.patch('json.dump') - def test_release_role_download_json(self, m_dump): - release_id = 45 - role_name = 'fake_role' - test_data = fake_role.get_fake_role(fake_role) - args = 'role download -r {} -n {} -f json -d /tmp'.format(release_id, - role_name) - expected_path = '/tmp/releases_{id}/{name}.json'.format(id=release_id, - name=role_name) - - self.m_client.get_one.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.get_one.assert_called_once_with('releases', - release_id, - role_name) - - @mock.patch('json.dump') - def test_cluster_role_download_json(self, m_dump): - env_id = 45 - role_name = 'fake_role' - test_data = fake_role.get_fake_role(fake_role) - args = 'role download -e {} -n {} -f json -d /tmp'.format(env_id, - role_name) - expected_path = '/tmp/clusters_{id}/{name}.json'.format(id=env_id, - name=role_name) - - self.m_client.get_one.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.get_one.assert_called_once_with('clusters', - env_id, - role_name) - - @mock.patch('yaml.safe_dump') - def test_release_role_download_yaml(self, m_safe_dump): - release_id = 45 - role_name = 'fake_role' - test_data = fake_role.get_fake_role(fake_role) - args = 'role download -r {} -n {} -f yaml -d /tmp'.format(release_id, - role_name) - expected_path = '/tmp/releases_{id}/{name}.yaml'.format(id=release_id, - name=role_name) - - self.m_client.get_one.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.get_one.assert_called_once_with('releases', - release_id, - role_name) - - @mock.patch('yaml.safe_dump') - def test_cluster_role_download_yaml(self, m_safe_dump): - env_id = 45 - role_name = 'fake_role' - test_data = fake_role.get_fake_role(fake_role) - args = 'role download -e {} -n {} -f yaml -d /tmp'.format(env_id, - role_name) - expected_path = '/tmp/clusters_{id}/{name}.yaml'.format(id=env_id, - name=role_name) - - self.m_client.get_one.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.get_one.assert_called_once_with('clusters', - env_id, - role_name) - - def test_release_role_update_json(self): - release_id = 45 - role_name = 'fake_role' - params = {"owner_type": "releases", - "owner_id": release_id, - "role_name": role_name} - args = 'role update -r {} -n {} -f json -d /tmp'.format(release_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/releases_{}/fake_role.json'.format(release_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_cluster_role_update_json(self): - env_id = 45 - role_name = 'fake_role' - params = {"owner_type": "clusters", - "owner_id": env_id, - "role_name": role_name} - args = 'role update -e {} -n {} -f json -d /tmp'.format(env_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/clusters_{}/fake_role.json'.format(env_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_release_role_update_yaml(self): - release_id = 45 - role_name = 'fake_role' - params = {"owner_type": "releases", - "owner_id": release_id, - "role_name": role_name} - args = 'role update -r {} -n {} -f yaml -d /tmp'.format(release_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/releases_{}/fake_role.yaml'.format(release_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_cluster_role_update_yaml(self): - env_id = 45 - role_name = 'fake_role' - params = {"owner_type": "clusters", - "owner_id": env_id, - "role_name": role_name} - args = 'role update -e {} -n {} -f yaml -d /tmp'.format(env_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/clusters_{}/fake_role.yaml'.format(env_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_release_role_create_json(self): - release_id = 45 - role_name = 'fake_role' - params = {"owner_type": "releases", - "owner_id": release_id, - "role_name": role_name} - args = 'role create -r {} -n {} -f json -d /tmp'.format(release_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/releases_{}/fake_role.json'.format(release_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_cluster_role_create_json(self): - env_id = 45 - role_name = 'fake_role' - params = {"owner_type": "clusters", - "owner_id": env_id, - "role_name": role_name} - args = 'role create -e {} -n {} -f json -d /tmp'.format(env_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/clusters_{}/fake_role.json'.format(env_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_release_role_create_yaml(self): - release_id = 45 - role_name = 'fake_role' - params = {"owner_type": "releases", - "owner_id": release_id, - "role_name": role_name} - args = 'role create -r {} -n {} -f yaml -d /tmp'.format(release_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/releases_{}/fake_role.yaml'.format(release_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_cluster_role_create_yaml(self): - env_id = 45 - role_name = 'fake_role' - params = {"owner_type": "clusters", - "owner_id": env_id, - "role_name": role_name} - args = 'role create -e {} -n {} -f yaml -d /tmp'.format(env_id, - role_name) - test_data = fake_role.get_fake_role(role_name) - expected_path = '/tmp/clusters_{}/fake_role.yaml'.format(env_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.role.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_release_role_delete(self): - release_id = 45 - role_name = 'fake_role' - args = 'role delete -r {} -n {}'.format(release_id, role_name) - - self.exec_command(args) - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.delete.assert_called_once_with('releases', - release_id, - role_name) - - def test_cluster_role_delete(self): - env_id = 45 - role_name = 'fake_role' - args = 'role delete -e {} -n {}'.format(env_id, role_name) - - self.exec_command(args) - self.m_get_client.assert_called_once_with('role', mock.ANY) - self.m_client.delete.assert_called_once_with('clusters', - env_id, - role_name) diff --git a/fuelclient/tests/unit/v2/cli/test_sequences.py b/fuelclient/tests/unit/v2/cli/test_sequences.py deleted file mode 100644 index 68453cbc..00000000 --- a/fuelclient/tests/unit/v2/cli/test_sequences.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine - - -class TestSequenceActions(test_engine.BaseCLITest): - def test_create(self): - self.exec_command( - 'sequence create -r 1 -n test -t test_graph' - ) - self.m_client.create.assert_called_once_with( - 1, 'test', ['test_graph'] - ) - - def test_upload(self): - m_open = mock.mock_open(read_data='name: test\ngraphs: [test]') - module_path = 'fuelclient.cli.serializers.open' - with mock.patch(module_path, m_open, create=True): - self.exec_command( - 'sequence upload -r 1 --file sequence.yaml' - ) - - self.m_client.upload.assert_called_once_with( - 1, {'name': 'test', 'graphs': ['test']} - ) - - def test_download(self): - self.m_client.download.return_value = {"name": "test"} - m_open = mock.mock_open() - module_path = 'fuelclient.cli.serializers.open' - with mock.patch(module_path, m_open, create=True): - self.exec_command( - 'sequence download 1 --file sequence.json' - ) - self.m_client.download.assert_called_once_with(1) - with mock.patch('sys.stdout') as stdout_mock: - self.exec_command('sequence download 1') - stdout_mock.write.assert_called_with("name: test\n") - - def test_update(self): - self.exec_command( - 'sequence update 1 -n test -t test_graph' - ) - self.m_client.update.assert_called_once_with( - 1, name='test', graph_types=['test_graph'] - ) - - def test_show(self): - self.exec_command('sequence show 1') - self.m_client.get_by_id.assert_called_once_with(1) - - def test_list(self): - self.exec_command('sequence list -r 1') - self.m_client.get_all.assert_called_once_with(release=1) - - def test_delete(self): - self.exec_command('sequence delete 1') - self.m_client.delete_by_id.assert_called_once_with(1) - - def test_execute_with_dry_run_and_force(self): - self.exec_command( - 'sequence execute 1 -e 2 --dry-run --force' - ) - self.m_client.execute.assert_called_once_with( - sequence_id=1, env_id=2, - dry_run=True, noop_run=False, force=True, debug=False - ) - - def test_execute_with_noop_and_trace(self): - self.exec_command( - 'sequence execute 1 -e 2 --noop --trace' - ) - self.m_client.execute.assert_called_once_with( - sequence_id=1, env_id=2, - dry_run=False, noop_run=True, force=False, debug=True - ) - - def test_execute_with_json_output(self): - self.m_client.execute.return_value = mock.MagicMock( - data={'id': 1} - ) - with mock.patch('sys.stdout') as stdout_mock: - self.exec_command('sequence execute 1 -e 2 --format=json') - stdout_mock.write.assert_called_with('{\n "id": 1\n}\n') diff --git a/fuelclient/tests/unit/v2/cli/test_snapshot.py b/fuelclient/tests/unit/v2/cli/test_snapshot.py deleted file mode 100644 index d9f04578..00000000 --- a/fuelclient/tests/unit/v2/cli/test_snapshot.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 json -import mock -import yaml - -from fuelclient.cli import error -from fuelclient.tests.unit.v2.cli import test_engine - - -class TestSnapshotCommand(test_engine.BaseCLITest): - - @mock.patch('json.dump') - def test_snapshot_config_download_json(self, m_dump): - args = 'snapshot get-default-config -f json -d /tmp' - test_data = {'foo': 'bar'} - expected_path = '/tmp/snapshot_conf.json' - - self.m_client.get_default_config.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.snapshot.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('snapshot', mock.ANY) - self.m_client.get_default_config.assert_called_once_with() - - @mock.patch('yaml.safe_dump') - def test_snapshot_config_download_yaml(self, m_safe_dump): - args = 'snapshot get-default-config -f yaml -d /tmp' - test_data = {'foo': 'bar'} - expected_path = '/tmp/snapshot_conf.yaml' - - self.m_client.get_default_config.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.snapshot.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - - self.m_get_client.assert_called_once_with('snapshot', mock.ANY) - self.m_client.get_default_config.assert_called_once_with() - - def test_snapshot_create(self): - args = 'snapshot create' - test_data = {} - self.exec_command(args) - - self.m_get_client.assert_called_once_with('snapshot', mock.ANY) - self.m_client.create_snapshot.assert_called_once_with(test_data) - - @mock.patch('fuelclient.utils.file_exists', mock.Mock(return_value=True)) - def test_snapshot_create_w_config_json(self): - args = 'snapshot create -c /tmp/snapshot_conf.json' - test_data = {'foo': 'bar'} - expected_path = '/tmp/snapshot_conf.json' - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.snapshot.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('snapshot', mock.ANY) - self.m_client.create_snapshot.assert_called_once_with(test_data) - - @mock.patch('fuelclient.utils.file_exists', mock.Mock(return_value=True)) - def test_snapshot_create_w_config_yaml(self): - args = 'snapshot create -c /tmp/snapshot_conf.yaml' - test_data = {'foo': 'bar'} - expected_path = '/tmp/snapshot_conf.yaml' - - m_open = mock.mock_open(read_data=yaml.dump(test_data)) - with mock.patch('fuelclient.commands.snapshot.open', - m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('snapshot', mock.ANY) - self.m_client.create_snapshot.assert_called_once_with(test_data) - - def test_snapshot_get_link(self): - task_id = 45 - args = 'snapshot get-link {}'.format(task_id) - test_data = {'id': task_id, - 'name': 'dump', - 'status': 'ready', - 'message': 'fake_message'} - - self.m_client.get_by_id.return_value = test_data - - self.exec_command(args) - self.m_get_client.assert_called_once_with('snapshot', mock.ANY) - self.m_client.get_by_id.assert_called_once_with(task_id) - - @mock.patch('sys.stderr') - def test_snapshot_get_link_fail(self, mocked_stderr): - task_id = 45 - args = 'snapshot get-link {}'.format(task_id) - test_data = {'id': task_id, - 'name': 'not_dump_name', - 'status': 'ready', - 'message': 'fake_message'} - - self.m_client.get_by_id.return_value = test_data - - self.assertRaises(error.ActionException, self.exec_command, args) - self.assertIn('Task with id {} is not a snapshot generation ' - 'task'.format(task_id), - mocked_stderr.write.call_args_list[0][0][0]) diff --git a/fuelclient/tests/unit/v2/cli/test_tag.py b/fuelclient/tests/unit/v2/cli/test_tag.py deleted file mode 100644 index c13fbeff..00000000 --- a/fuelclient/tests/unit/v2/cli/test_tag.py +++ /dev/null @@ -1,367 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 json -import mock -import yaml - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests.utils import fake_tag - - -class TestTagCommand(test_engine.BaseCLITest): - """Tests for fuel2 tag * commands.""" - - def test_tag_list_for_release(self): - self.m_client.get_all.return_value = [ - {"tag": "fake_tag_1", - "has_primary": True, - "owner_id": 1, - "owner_type": 'release', - }, - {"tag": "fake_tag_2", - "has_primary": True, - "owner_id": 1, - "owner_type": 'release', - }, - ] - release_id = 45 - args = 'tag list -r {id}'.format(id=release_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with('releases', release_id) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - - def test_tag_list_for_cluster(self): - self.m_client.get_all.return_value = [ - {"tag": "fake_tag_1", - "has_primary": True, - "owner_id": 1, - "owner_type": 'release', - }, - {"tag": "fake_tag_2", - "has_primary": True, - "owner_id": 1, - "owner_type": 'release', - }, - ] - env_id = 45 - args = 'tag list -e {id}'.format(id=env_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with('clusters', env_id) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - - def test_tag_list_sorted(self): - self.m_client.get_all.return_value = [ - {"tag": "fake_tag_2", - "group": "group_1", - "has_primary": True, - "owner_id": 1, - "owner_type": 'release', - }, - {"tag": "fake_tag_1", - "group": "group_2", - "has_primary": True, - "owner_id": 1, - "owner_type": 'release', - } - ] - env_id = 45 - args = 'tag list -e {id} -s group'.format(id=env_id) - self.exec_command(args) - self.m_client.get_all.assert_called_once_with('clusters', env_id) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - - @mock.patch('sys.stderr') - def test_tag_list_fail(self, mocked_stderr): - args = 'tag list' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-r/--release -e/--env', - mocked_stderr.write.call_args_list[-1][0][0]) - - @mock.patch('sys.stderr') - def test_tag_list_with_mutually_exclusive_params(self, mocked_stderr): - args = 'tag list -e 1 -r 2' - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('not allowed', - mocked_stderr.write.call_args_list[-1][0][0]) - - @mock.patch('json.dump') - def test_release_tag_download_json(self, m_dump): - release_id = 45 - tag_name = 'fake_tag' - test_data = fake_tag.get_fake_tag(fake_tag) - args = 'tag download -r {} -n {} -f json -d /tmp'.format(release_id, - tag_name) - expected_path = '/tmp/releases_{id}/{name}.json'.format(id=release_id, - name=tag_name) - - self.m_client.get_tag.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.get_tag.assert_called_once_with('releases', - release_id, - tag_name) - - @mock.patch('json.dump') - def test_cluster_tag_download_json(self, m_dump): - env_id = 45 - tag_name = 'fake_tag' - test_data = fake_tag.get_fake_tag(fake_tag) - args = 'tag download -e {} -n {} -f json -d /tmp'.format(env_id, - tag_name) - expected_path = '/tmp/clusters_{id}/{name}.json'.format(id=env_id, - name=tag_name) - - self.m_client.get_tag.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_dump.assert_called_once_with(test_data, mock.ANY, indent=4) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.get_tag.assert_called_once_with('clusters', - env_id, - tag_name) - - @mock.patch('yaml.safe_dump') - def test_release_tag_download_yaml(self, m_safe_dump): - release_id = 45 - tag_name = 'fake_tag' - test_data = fake_tag.get_fake_tag(fake_tag) - args = 'tag download -r {} -n {} -f yaml -d /tmp'.format(release_id, - tag_name) - expected_path = '/tmp/releases_{id}/{name}.yaml'.format(id=release_id, - name=tag_name) - - self.m_client.get_tag.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.get_tag.assert_called_once_with('releases', - release_id, - tag_name) - - @mock.patch('yaml.safe_dump') - def test_cluster_tag_download_yaml(self, m_safe_dump): - env_id = 45 - tag_name = 'fake_tag' - test_data = fake_tag.get_fake_tag(fake_tag) - args = 'tag download -e {} -n {} -f yaml -d /tmp'.format(env_id, - tag_name) - expected_path = '/tmp/clusters_{id}/{name}.yaml'.format(id=env_id, - name=tag_name) - - self.m_client.get_tag.return_value = test_data - - m_open = mock.mock_open() - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'w') - m_safe_dump.assert_called_once_with(test_data, mock.ANY, - default_flow_style=False) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.get_tag.assert_called_once_with('clusters', - env_id, - tag_name) - - def test_release_tag_update_json(self): - release_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "releases", - "owner_id": release_id, - "tag_name": tag_name} - args = 'tag update -r {} -n {} -f json -d /tmp'.format(release_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/releases_{}/fake_tag.json'.format(release_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_cluster_tag_update_json(self): - env_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "clusters", - "owner_id": env_id, - "tag_name": tag_name} - args = 'tag update -e {} -n {} -f json -d /tmp'.format(env_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/clusters_{}/fake_tag.json'.format(env_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_release_tag_update_yaml(self): - release_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "releases", - "owner_id": release_id, - "tag_name": tag_name} - args = 'tag update -r {} -n {} -f yaml -d /tmp'.format(release_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/releases_{}/fake_tag.yaml'.format(release_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_cluster_tag_update_yaml(self): - env_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "clusters", - "owner_id": env_id, - "tag_name": tag_name} - args = 'tag update -e {} -n {} -f yaml -d /tmp'.format(env_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/clusters_{}/fake_tag.yaml'.format(env_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.update.assert_called_once_with(test_data, **params) - - def test_release_tag_create_json(self): - release_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "releases", - "owner_id": release_id, - "tag_name": tag_name} - args = 'tag create -r {} -n {} -f json -d /tmp'.format(release_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/releases_{}/fake_tag.json'.format(release_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_cluster_tag_create_json(self): - env_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "clusters", - "owner_id": env_id, - "tag_name": tag_name} - args = 'tag create -e {} -n {} -f json -d /tmp'.format(env_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/clusters_{}/fake_tag.json'.format(env_id) - - m_open = mock.mock_open(read_data=json.dumps(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_release_tag_create_yaml(self): - release_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "releases", - "owner_id": release_id, - "tag_name": tag_name} - args = 'tag create -r {} -n {} -f yaml -d /tmp'.format(release_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/releases_{}/fake_tag.yaml'.format(release_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_cluster_tag_create_yaml(self): - env_id = 45 - tag_name = 'fake_tag' - params = {"owner_type": "clusters", - "owner_id": env_id, - "tag_name": tag_name} - args = 'tag create -e {} -n {} -f yaml -d /tmp'.format(env_id, - tag_name) - test_data = fake_tag.get_fake_tag(tag_name) - expected_path = '/tmp/clusters_{}/fake_tag.yaml'.format(env_id) - - m_open = mock.mock_open(read_data=yaml.safe_dump(test_data)) - with mock.patch('fuelclient.commands.tag.open', m_open, create=True): - self.exec_command(args) - - m_open.assert_called_once_with(expected_path, 'r') - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.create.assert_called_once_with(test_data, **params) - - def test_release_tag_delete(self): - release_id = 45 - tag_name = 'fake_tag' - args = 'tag delete -r {} -n {}'.format(release_id, tag_name) - - self.exec_command(args) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.delete.assert_called_once_with('releases', - release_id, - tag_name) - - def test_cluster_tag_delete(self): - env_id = 45 - tag_name = 'fake_tag' - args = 'tag delete -e {} -n {}'.format(env_id, tag_name) - - self.exec_command(args) - self.m_get_client.assert_called_once_with('tag', mock.ANY) - self.m_client.delete.assert_called_once_with('clusters', - env_id, - tag_name) diff --git a/fuelclient/tests/unit/v2/cli/test_task.py b/fuelclient/tests/unit/v2/cli/test_task.py deleted file mode 100644 index fd7227a2..00000000 --- a/fuelclient/tests/unit/v2/cli/test_task.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 mock -import os -import yaml - -from fuelclient.tests.unit.v2.cli import test_engine -from fuelclient.tests import utils -from fuelclient.v1.deployment_history import DeploymentHistoryClient - - -class TestTaskCommand(test_engine.BaseCLITest): - - def setUp(self): - super(TestTaskCommand, self).setUp() - - self.m_client.get_all.return_value = [utils.get_fake_task() - for _ in range(10)] - self.m_client.get_by_id.return_value = utils.get_fake_task() - self.current_path = os.path.join(os.path.abspath(os.curdir)) - - def test_task_list(self): - args = 'task list' - self.exec_command(args) - - self.m_get_client.assert_called_once_with('task', mock.ANY) - self.m_client.get_all.assert_called_once_with() - - def test_task_list_w_parameters(self): - env_id = 45 - statuses = ['ready', 'error'] - names = ['provision', 'dump'] - args = 'task list -e {env_id} -t {statuses} -n {names}'.format( - env_id=env_id, - statuses=' '.join(statuses), - names=' '.join(names)) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('task', mock.ANY) - self.m_client.get_all.assert_called_once_with(cluster_id=env_id, - statuses=statuses, - transaction_types=names) - - @mock.patch('sys.stderr') - def test_task_list_w_wrong_parameters(self, mocked_stderr): - statuses = ['ready', 'wrong_status'] - args = 'task list -t {statuses}'.format(statuses=' '.join(statuses)) - self.assertRaises(SystemExit, self.exec_command, args) - self.assertIn('-t/--statuses: invalid choice', - mocked_stderr.write.call_args_list[-1][0][0]) - - def test_task_show(self): - task_id = 42 - args = 'task show {task_id}'.format(task_id=task_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('task', mock.ANY) - self.m_client.get_by_id.assert_called_once_with(task_id) - - def test_task_delete(self): - task_id = 42 - args = 'task delete {task_id}'.format(task_id=task_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('task', mock.ANY) - self.m_client.delete_by_id.assert_called_once_with(task_id, False) - - def test_task_delete_force(self): - task_id = 42 - args = 'task delete --force {task_id}'.format(task_id=task_id) - - self.exec_command(args) - - self.m_get_client.assert_called_once_with('task', mock.ANY) - self.m_client.delete_by_id.assert_called_once_with(task_id, True) - - def test_task_history_show(self): - task_id = 42 - args = 'task history show {task_id} '.format(task_id=task_id) - - self.m_client.get_all.return_value = \ - utils.get_fake_deployment_history() - self.exec_command(args) - - self.m_get_client.assert_called_once_with('deployment_history', - mock.ANY) - self.m_client.get_all.assert_called_once_with(transaction_id=task_id, - nodes=None, - statuses=None, - tasks_names=None, - include_summary=False, - show_parameters=False) - - def test_task_history_show_include_summary(self): - task_id = 42 - args = 'task history show {task_id} '.format(task_id=task_id) - args += '--include-summary ' - - self.m_client.get_all.return_value = \ - utils.get_fake_deployment_history(include_summary=True) - self.exec_command(args) - - self.m_get_client.assert_called_once_with('deployment_history', - mock.ANY) - self.m_client.get_all.assert_called_once_with(transaction_id=task_id, - nodes=None, - statuses=None, - tasks_names=None, - include_summary=True, - show_parameters=False) - - def test_task_history_parameters(self): - task_id = 42 - args = 'task history show {task_id} ' \ - '--tasks-names task1 task2 ' \ - '--statuses ready error --nodes 1 2 ' \ - '--show-parameters'.format(task_id=task_id) - - self.m_client.get_all.return_value = \ - utils.get_fake_deployment_history() - self.exec_command(args) - - self.m_get_client.assert_called_once_with('deployment_history', - mock.ANY) - self.m_client.get_all.assert_called_once_with( - transaction_id=task_id, nodes=['1', '2'], - statuses=['ready', 'error'], tasks_names=['task1', 'task2'], - include_summary=False, - show_parameters=True) - - def _test_cmd(self, cmd, method, cmd_line, client, - return_data, expected_file_path, expected_kwargs): - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - self.m_client.__getattr__(method).return_value =\ - yaml.safe_load(return_data) - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.exec_command('task {0} {1} {2}'.format(cmd, method, - cmd_line)) - - m_open.assert_called_once_with(expected_file_path, 'w') - written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0]) - expected_yaml = yaml.safe_load(return_data) - self.assertEqual(written_yaml, expected_yaml) - - self.m_get_client.assert_called_once_with(client, mock.ANY) - self.m_client.__getattr__(method).assert_called_once_with( - **expected_kwargs) - - def test_task_deployment_info_download(self): - self._test_cmd('deployment-info', 'download', '1 ', - 'deployment-info', - utils.get_fake_yaml_deployment_info(), - "{0}/deployment_info_1.yaml".format( - self.current_path), - dict(transaction_id=1)) - - def test_task_cluster_settings_download(self): - self._test_cmd('settings', 'download', '1 --file settings.yaml', - 'cluster-settings', - utils.get_fake_yaml_cluster_settings(), - 'settings.yaml', - dict(transaction_id=1)) - - def test_task_network_configuration_download(self): - self._test_cmd('network-configuration', 'download', '1', - 'network-configuration', - utils.get_fake_yaml_network_conf(), - "{0}/network_configuration_1.yaml".format( - self.current_path), - dict(transaction_id=1)) - - -class TestDeploymentTasksAction(test_engine.BaseCLITest): - - @mock.patch('cliff.formatters.table.TableFormatter.emit_list') - def test_show_tasks_history_with_parameters(self, m_formatter): - tasks_after_facade = utils.get_fake_deployment_history_w_params() - - expected_fields = ('task_name', 'task_parameters', 'status_by_node') - expected_data = [ - [ - 'controller-remaining-tasks', - - 'parameters: {puppet_manifest: /etc/puppet/modules/osnailyfact' - 'er/modular/globals/globals.pp,\n puppet_modules: /etc/' - 'puppet/modules, timeout: 3600}\nrole: [controller]\ntype: ' - 'puppet\nversion: 2.0.0\n', - - '1 - ready - 2016-03-25T17:22:10 - 2016-03-25T17:22:30\n' - '2 - ready - 2016-03-25T17:22:10 - 2016-03-25T17:22:30' - ], - [ - 'pending-task', - - 'parameters: {puppet_manifest: /etc/puppet/modules/osnailyfact' - 'er/modular/globals/globals.pp,\n puppet_modules: /etc/puppet' - '/modules, timeout: 3600}\nrole: [controller]\ntype: ' - 'puppet\nversion: 2.0.0\n', - - '1 - pending - not started - not ended\n' - '2 - pending - not started - not ended' - ], - [ - 'ironic-compute', - 'parameters: {puppet_manifest: /etc/puppet/modules/osnailyfact' - 'er/modular/globals/globals.pp,\n puppet_modules: /etc/' - 'puppet/modules, timeout: 3600}\nrole: [controller]\ntype: ' - 'puppet\nversion: 2.0.0\n', - - '1 - skipped - 2016-03-25T17:23:37 - 2016-03-25T17:23:37\n' - '2 - skipped - 2016-03-25T17:23:37 - 2016-03-25T17:23:37' - ] - ] - self.m_client.get_all.return_value = tasks_after_facade - self.m_client.tasks_records_keys = \ - DeploymentHistoryClient.tasks_records_keys - self.m_client.history_records_keys = \ - DeploymentHistoryClient.history_records_keys - - self.exec_command( - ' '.join(( - 'task history show', '1', - '--nodes', '1 2', - '--statuses', 'ready', - '--tasks-names', 'taskname1 taskname2', - '--show-parameters' - )) - ) - - self.m_client.get_all.assert_called_with( - nodes=['1', '2'], - statuses=['ready'], - tasks_names=['taskname1', 'taskname2'], - transaction_id=1, - include_summary=False, - show_parameters=True) - - m_formatter.assert_called_once_with(expected_fields, - expected_data, - mock.ANY, - mock.ANY) diff --git a/fuelclient/tests/unit/v2/cli/test_vip.py b/fuelclient/tests/unit/v2/cli/test_vip.py deleted file mode 100644 index 1118166b..00000000 --- a/fuelclient/tests/unit/v2/cli/test_vip.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock - -from fuelclient.tests.unit.v2.cli import test_engine - - -class TestVIPActions(test_engine.BaseCLITest): - - def _test_cmd(self, method, cmd_line, expected_kwargs): - self.m_get_client.reset_mock() - self.m_client.get_filtered.reset_mock() - self.m_client.__getattr__(method).return_value = 'vips_1.yaml' - self.exec_command('vip {0} {1}'.format(method, cmd_line)) - self.m_get_client.assert_called_once_with('vip', mock.ANY) - self.m_client.__getattr__(method).assert_called_once_with( - **expected_kwargs) - - def test_vip_create(self): - expected = { - "env_id": 1, - "ip_addr": '127.0.0.1', - "network": 1, - "vip_name": 'test', - "vip_namespace": 'test-namespace' - } - cmd_line = ( - '--env {0} --network {1} --address {2} --name {3} --namespace {4}' - .format(expected['env_id'], expected['network'], - expected['ip_addr'], expected['vip_name'], - expected['vip_namespace']) - ) - self._test_cmd('create', cmd_line, expected) - - def test_vip_download(self): - self._test_cmd('download', '--env 1', dict( - env_id=1, - file_path=None, - ip_addr_id=None, - network_id=None, - network_role=None)) - - def test_vip_download_with_network_id(self): - self._test_cmd('download', '--env 1 --network 3', dict( - env_id=1, - file_path=None, - ip_addr_id=None, - network_id=3, - network_role=None)) - - def test_vip_download_with_network_role(self): - self._test_cmd('download', '--env 1 --network-role some/role', dict( - env_id=1, - file_path=None, - ip_addr_id=None, - network_id=None, - network_role='some/role')) - - def test_single_vip_download(self): - self._test_cmd('download', '--env 1 --ip-address-id 5', dict( - env_id=1, - file_path=None, - ip_addr_id=5, - network_id=None, - network_role=None)) - - def test_vip_upload(self): - self._test_cmd('upload', '--env 1 --file vips_1.yaml', dict( - env_id=1, - file_path='vips_1.yaml')) diff --git a/fuelclient/tests/unit/v2/lib/__init__.py b/fuelclient/tests/unit/v2/lib/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/fuelclient/tests/unit/v2/lib/test_api.py b/fuelclient/tests/unit/v2/lib/test_api.py deleted file mode 100644 index 15eecf7f..00000000 --- a/fuelclient/tests/unit/v2/lib/test_api.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 mock -from mock import patch -from oslotest import base as oslo_base -import requests_mock as rm -from six.moves.urllib import parse as urlparse - -from fuelclient import client - - -class BaseLibTest(oslo_base.BaseTestCase): - def setUp(self): - super(BaseLibTest, self).setUp() - - self.m_request = rm.Mocker() - self.m_request.start() - - self.auth_required_patch = patch.object(client.APIClient, - 'auth_required', - new_callable=mock.PropertyMock) - self.m_auth_required = self.auth_required_patch.start() - self.m_auth_required.return_value = False - - self.addCleanup(self.m_request.stop) - self.addCleanup(self.auth_required_patch.stop) - - def get_object_uri(self, collection_path, object_id, attribute='/'): - return urlparse.urljoin(collection_path, str(object_id) + attribute) diff --git a/fuelclient/tests/unit/v2/lib/test_client.py b/fuelclient/tests/unit/v2/lib/test_client.py deleted file mode 100644 index 8f11d667..00000000 --- a/fuelclient/tests/unit/v2/lib/test_client.py +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2016 Mirantis, 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 fuelclient -from fuelclient.objects import base -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.v1 import base_v1 - - -class FakeObject(base.BaseObject): - class_api_path = 'fake/objects/' - - -class FakeClient(base_v1.BaseV1Client): - - _entity_wrapper = FakeObject - - -class TestClient(test_api.BaseLibTest): - - def setUp(self): - super(TestClient, self).setUp() - - self.host = 'test.host.tld' - self.port = 8888 - - self.connection = fuelclient.connect(self.host, self.port) - - self.client = FakeClient(connection=self.connection) - - self.version = 'v1' - self.res_uri = '/api/{version}/fake/objects/'.format( - version=self.version) - - def test_custom_connection_used(self): - m_get = self.m_request.get(self.res_uri, json={}) - self.client.get_all() - - self.assertTrue(m_get.called) - self.assertEqual( - m_get.last_request.netloc, - '{host}:{port}'.format(host=self.host, port=self.port)) diff --git a/fuelclient/tests/unit/v2/lib/test_deployment_graph.py b/fuelclient/tests/unit/v2/lib/test_deployment_graph.py deleted file mode 100644 index 234a568f..00000000 --- a/fuelclient/tests/unit/v2/lib/test_deployment_graph.py +++ /dev/null @@ -1,377 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock -import yaml - -import fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -TASKS_YAML = '''- id: custom-task-1 - type: puppet - parameters: - param: value -- id: custom-task-2 - type: puppet - parameters: - param: value -''' - - -class TestDeploymentGraphFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestDeploymentGraphFacade, self).setUp() - self.version = 'v1' - self.client = fuelclient.get_client('graph', self.version) - self.env_id = 1 - - def test_existing_graph_upload(self): - expected_body = { - 'tasks': yaml.load(TASKS_YAML)} - - matcher_post = self.m_request.post( - '/api/v1/clusters/1/deployment_graphs/custom_graph', - json=expected_body) - - matcher_get = self.m_request.get( - '/api/v1/clusters/1/deployment_graphs/custom_graph', - status_code=404, - json={'status': 'error', 'message': 'Does not exist'}) - - m_open = mock.mock_open(read_data=TASKS_YAML) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True): - self.client.upload( - data=expected_body, - related_model='clusters', - related_id=1, - graph_type='custom_graph' - ) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_post.called) - self.assertItemsEqual( - expected_body, - matcher_post.last_request.json() - ) - - def test_new_graph_upload(self): - expected_body = { - 'tasks': yaml.load(TASKS_YAML)} - - matcher_put = self.m_request.put( - '/api/v1/clusters/1/deployment_graphs/custom_graph', - json=expected_body) - - matcher_get = self.m_request.get( - '/api/v1/clusters/1/deployment_graphs/custom_graph', - status_code=200, - json={ - 'tasks': [{'id': 'imatask', 'type': 'puppet'}] - }) - - m_open = mock.mock_open(read_data=TASKS_YAML) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True): - self.client.upload( - data=expected_body, - related_model='clusters', - related_id=1, - graph_type='custom_graph') - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertItemsEqual( - expected_body, - matcher_put.last_request.json() - ) - - def test_new_graph_run_wo_params(self): - matcher_execute = self.m_request.post( - '/api/v1/graphs/execute/', - json=utils.fake_task.get_fake_task(cluster=370)) - # this is required to form running task info - self.m_request.get( - '/api/v1/nodes/?cluster_id=370', - json={} - ) - self.client.execute(env_id=1) - self.assertEqual( - matcher_execute.last_request.json(), - { - 'cluster': 1 - } - ) - - def test_new_graph_run_with_parameters(self): - matcher_execute = self.m_request.post( - '/api/v1/graphs/execute/', - json=utils.fake_task.get_fake_task(cluster=370)) - # this is required to form running task info - self.m_request.get( - '/api/v1/nodes/?cluster_id=370', - json={} - ) - self.client.execute( - env_id=1, - nodes=[1, 2, 3], - graph_types=["custom_graph", "another_custom_graph"], - task_names=["rsync_core_puppet"], - dry_run=True, - noop_run=True, - force=True - ) - self.assertEqual( - { - 'cluster': 1, - 'dry_run': True, - 'noop_run': True, - 'graphs': [ - {'nodes': [1, 2, 3], 'type': 'custom_graph', - 'tasks': ['rsync_core_puppet']}, - {'nodes': [1, 2, 3], 'type': 'another_custom_graph', - 'tasks': ['rsync_core_puppet']} - ], - 'force': True - }, - matcher_execute.last_request.json() - ) - - def test_env_graphs_list(self): - release_id = 101 - env_id = 11 - fake_env = utils.get_fake_env(release_id=release_id, env_id=env_id) - enabled_plugin_id = 331 - self.m_request.get( - '/api/v1/clusters/{}/'.format(env_id), - json=fake_env - ) - - self.m_request.get( - '/api/v1/clusters/{}/attributes'.format(env_id), - json={ - 'editable': { - 'test-plugin-1': { - 'metadata': { - 'class': 'plugin', - 'enabled': True, - 'chosen_id': enabled_plugin_id - } - }, - 'test-plugin-2': { - 'metadata': { - 'class': 'plugin', - 'enabled': False, - } - } - } - } - ) - - release_graphs = [ - { - "tasks": [], - "id": 1, - "relations": [ - { - "model_id": release_id, - "model": "release", - "type": "default" - } - ], - "name": None - } - ] - enabled_plugin_graphs = [ - { - "tasks": [], - "id": 2, - "relations": [ - { - "model_id": enabled_plugin_id, - "model": "plugin", - "type": "default" - } - ], - "name": None - } - ] - cluster_graphs = [ - { - "tasks": [], - "id": 3, - "relations": [ - { - "model_id": env_id, - "model": "cluster", - "type": "default" - } - ], - "name": None - } - ] - - all_env_graphs = \ - release_graphs + cluster_graphs + enabled_plugin_graphs - - not_this_env_cluster_graphs = [ - { - "tasks": [], - "id": 4, - "relations": [ - { - "model_id": env_id + 1, - "model": "cluster", - "type": "default" - } - ], - "name": None - } - ] - - self.m_request.get( - '/api/v1/releases/{}/deployment_graphs/'.format(release_id), - json=release_graphs - ) - - self.m_request.get( - '/api/v1/plugins/{}/deployment_graphs/'.format(enabled_plugin_id), - json=enabled_plugin_graphs - ) - - self.m_request.get( - '/api/v1/clusters/{}/deployment_graphs/'.format(env_id), - json=cluster_graphs - ) - - self.m_request.get( - '/api/v1/graphs/'.format(env_id), - json=all_env_graphs + not_this_env_cluster_graphs - ) - - self.assertItemsEqual( - all_env_graphs, self.client.list(env_id) - ) - self.assertItemsEqual( - release_graphs, self.client.list(env_id, filters=['release']) - ) - - self.assertItemsEqual( - enabled_plugin_graphs, - self.client.list(env_id, filters=['plugin']) - ) - - self.assertItemsEqual( - cluster_graphs, - self.client.list(env_id, filters=['cluster']) - ) - - self.assertItemsEqual( - all_env_graphs + not_this_env_cluster_graphs, - self.client.list() - ) - - self.assertItemsEqual( - cluster_graphs + not_this_env_cluster_graphs + release_graphs, - self.client.list(filters=['cluster', 'release'])) - - def test_new_graph_dry_run_subgraph(self): - matcher_post = self.m_request.post( - '/api/v1/graphs/execute/', - json=utils.get_fake_task(cluster=370)) - # this is required to form running task info - self.m_request.get( - '/api/v1/nodes/?cluster_id=370', - json={} - ) - self.client.execute( - env_id=1, - nodes=[1, 2, 3], - graph_types=["custom_graph"], - dry_run=True, - subgraphs=['primary-database/1,3:keystone-db/1-2,5', - 'openstack-controller'] - ) - self.assertTrue(matcher_post.called) - expected_body = {'cluster': 1, - 'dry_run': True, - 'graphs': - [{ - 'nodes': [1, 2, 3], 'type': 'custom_graph', - 'tasks': ['rsync_core_puppet']}, - { - 'nodes': [1, 2, 3], - 'type': 'another_custom_graph', - 'tasks': ['rsync_core_puppet']}], - 'subgraphs': [ - {'start': ['primary-database/1,3'], - 'end': ['keystone-db/1-2,5']}, - {'start': ['openstack-controller'], - 'end': [None]}] - } - self.assertItemsEqual(matcher_post.last_request.json(), expected_body) - - def test_graphs_download_all(self): - matcher_get = self.m_request.get( - '/api/v1/clusters/1/deployment_tasks/?graph_type=custom_graph', - json=[] - ) - self.client.download(env_id=1, level='all', - graph_type='custom_graph') - self.assertTrue(matcher_get.called) - - def test_graphs_download_release(self): - matcher_get = self.m_request.get( - '/api/v1/clusters/1/deployment_tasks/' - 'release/?graph_type=custom_graph', - json=[] - ) - self.client.download(env_id=1, level='release', - graph_type='custom_graph') - self.assertTrue(matcher_get.called) - - def test_graphs_download_plugins(self): - matcher_get = self.m_request.get( - '/api/v1/clusters/1/deployment_tasks/' - 'plugins/?graph_type=custom_graph', - json=[] - ) - self.client.download(env_id=1, level='plugins', - graph_type='custom_graph') - self.assertTrue(matcher_get.called) - - def test_graphs_download_cluster(self): - matcher_get = self.m_request.get( - '/api/v1/clusters/1/deployment_tasks/own/' - '?graph_type=custom_graph', - json=[{'tasks': []}] - ) - self.client.download(env_id=1, level='cluster', - graph_type='custom_graph') - self.assertTrue(matcher_get.called) - - def test_graph_delete(self): - matcher_delete = self.m_request.delete( - '/api/v1/clusters/1/deployment_graphs/custom_graph', - json={} - ) - self.client.delete(graph_type='custom_graph', - related_id=1, - related_model='clusters') - self.assertTrue(matcher_delete.called) diff --git a/fuelclient/tests/unit/v2/lib/test_deployment_history.py b/fuelclient/tests/unit/v2/lib/test_deployment_history.py deleted file mode 100644 index a79f5aa9..00000000 --- a/fuelclient/tests/unit/v2/lib/test_deployment_history.py +++ /dev/null @@ -1,126 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestDeploymentHistoryFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestDeploymentHistoryFacade, self).setUp() - - self.version = 'v1' - self.transaction_id = '1' - self.res_uri = '/api/{0}/transactions/{1}'\ - '/deployment_history/' \ - ''.format(self.version, self.transaction_id) - - self.fake_history = utils.get_fake_deployment_history() - - self.client = fuelclient.get_client('deployment_history', self.version) - - def get_url(self, nodes='', statuses='', tasks_names=''): - params = '?nodes={}&statuses={}&tasks_names={}' - return self.res_uri + params.format(nodes, statuses, tasks_names) - - def test_deployment_history_list(self): - - matcher = self.m_request.get(self.get_url(), json=self.fake_history) - - self.client.get_all( - transaction_id=self.transaction_id, - nodes=None, - statuses=None) - - self.assertTrue(matcher.called) - - def test_deployment_history(self): - - matcher = self.m_request.get( - self.get_url( - nodes='1,2', - statuses='ready,error,pending', - tasks_names='controller-remaining-tasks,' - 'ironic-compute,pending-task' - ), json=self.fake_history) - - tasks_after_facade = self.client.get_all( - transaction_id=self.transaction_id, - nodes=['1', '2'], - statuses=['ready', 'error', 'pending'], - tasks_names=['controller-remaining-tasks', - 'ironic-compute', 'pending-task'], - show_parameters=False - ) - - self.assertTrue(matcher.called) - self.assertItemsEqual( - utils.get_fake_deployment_history(convert_legacy_fields=True), - tasks_after_facade) - - def test_deployment_history_include_summary(self): - fake_history = utils.get_fake_deployment_history(include_summary=True) - matcher = self.m_request.get( - self.get_url( - nodes='1,2', - statuses='ready,error,pending', - tasks_names='controller-remaining-tasks,' - 'ironic-compute,pending-task' - ) + '&include_summary=1', json=fake_history) - - tasks_after_facade = self.client.get_all( - transaction_id=self.transaction_id, - nodes=['1', '2'], - statuses=['ready', 'error', 'pending'], - tasks_names=['controller-remaining-tasks', - 'ironic-compute', 'pending-task'], - include_summary=True, - show_parameters=False - ) - - self.assertTrue(matcher.called) - self.assertItemsEqual( - utils.get_fake_deployment_history(convert_legacy_fields=True, - include_summary=True), - tasks_after_facade) - - def test_deployment_history_parameters(self): - - matcher = self.m_request.get( - self.get_url( - nodes='1,2', - statuses='ready,error,pending', - tasks_names='controller-remaining-tasks,' - 'ironic-compute,pending-task' - ), - json=utils.get_fake_deployment_history(add_task_data=True), - ) - - tasks_after_facade = self.client.get_all( - transaction_id=self.transaction_id, - nodes=['1', '2'], - statuses=['ready', 'error', 'pending'], - tasks_names=['controller-remaining-tasks', - 'ironic-compute', 'pending-task'], - show_parameters=True - ) - - self.assertTrue(matcher.called) - self.assertItemsEqual( - utils.get_fake_deployment_history_w_params(), - tasks_after_facade) diff --git a/fuelclient/tests/unit/v2/lib/test_environment.py b/fuelclient/tests/unit/v2/lib/test_environment.py deleted file mode 100644 index e2cb9cdf..00000000 --- a/fuelclient/tests/unit/v2/lib/test_environment.py +++ /dev/null @@ -1,531 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 mock - -import fuelclient -from fuelclient.cli import error -from fuelclient.objects import base as base_object -from fuelclient.objects import environment as env_object -from fuelclient.objects import fuelversion as fuelversion_object -from fuelclient.objects import task as task_object -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestEnvFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestEnvFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/clusters/'.format(version=self.version) - self.net_conf_uri = '/network_configuration/neutron' - self.settings_uri = '/attributes' - self.net_verify_uri = '/network_configuration/neutron/verify' - - self.fake_env = utils.get_fake_env() - self.fake_envs = [utils.get_fake_env() for i in range(10)] - - self.client = fuelclient.get_client('environment', self.version) - - def test_env_list(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_envs) - self.client.get_all() - - self.assertTrue(matcher.called) - - def test_env_show(self): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id) - - matcher = self.m_request.get(expected_uri, json=self.fake_env) - - self.client.get_by_id(env_id) - - self.assertTrue(matcher.called) - - def test_env_delete(self): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id) - - matcher = self.m_request.delete(expected_uri, json={}) - - self.client.delete_by_id(env_id) - - self.assertTrue(matcher.called) - - @mock.patch.object(env_object.Environment, 'init_with_data') - def test_env_create(self, m_init): - env_name = self.fake_env['name'] - release_id = self.fake_env['release_id'] - nst = 'vlan' - - matcher = self.m_request.post(self.res_uri, json=self.fake_env) - - self.client.create(name=env_name, - release_id=release_id, - net_segment_type=nst) - - req_data = matcher.last_request.json() - - self.assertTrue(matcher.called) - - self.assertEqual(release_id, req_data['release_id']) - self.assertEqual(env_name, req_data['name']) - self.assertEqual(nst, req_data['net_segment_type']) - - def test_env_create_bad_nst_neutron(self): - node_name = 'test_node' - release_id = 20 - nst = 'bad' - - self.assertRaises(error.BadDataException, - self.client.create, - node_name, release_id, nst) - - def test_env_create_neutron_tun(self): - env = utils.get_fake_env() - env_name = env['name'] - release_id = env['release_id'] - nst = env['net_segment_type'] = 'tun' - - matcher = self.m_request.post(self.res_uri, json=env) - - self.client.create(name=env_name, - release_id=release_id, - net_segment_type=nst) - - req_data = matcher.last_request.json() - - self.assertEqual(release_id, req_data['release_id']) - self.assertEqual(env_name, req_data['name']) - self.assertEqual(nst, req_data['net_segment_type']) - - @mock.patch.object(task_object.DeployTask, 'init_with_data') - def test_env_deploy(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, '/changes') - matcher = self.m_request.put(expected_uri, json={}) - dry_run = False - - self.client.deploy_changes(env_id, dry_run=dry_run) - self.check_deploy_redeploy_changes(dry_run, matcher) - - def check_deploy_redeploy_changes(self, res, matcher, mode='dry_run'): - self.assertTrue(matcher.called) - self.assertEqual(matcher.last_request.qs[mode][0], str(int(res))) - - @mock.patch.object(task_object.DeployTask, 'init_with_data') - def test_env_deploy_dry_run(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, '/changes') - matcher = self.m_request.put(expected_uri, json={}) - - dry_run = True - - self.client.deploy_changes(env_id, dry_run=dry_run) - self.check_deploy_redeploy_changes(dry_run, matcher) - - @mock.patch.object(task_object.DeployTask, 'init_with_data') - def test_env_deploy_noop_run(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, '/changes') - matcher = self.m_request.put(expected_uri, json={}) - - noop_run = True - - self.client.deploy_changes(env_id, noop_run=noop_run) - self.check_deploy_redeploy_changes(noop_run, matcher, mode='noop_run') - - @mock.patch.object(task_object.DeployTask, 'init_with_data') - def test_env_redeploy(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, - '/changes/redeploy') - matcher = self.m_request.put(expected_uri, json={}) - dry_run = False - - self.client.redeploy_changes(env_id, dry_run=dry_run) - self.check_deploy_redeploy_changes(dry_run, matcher) - - @mock.patch.object(task_object.DeployTask, 'init_with_data') - def test_env_redeploy_dry_run(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, - '/changes/redeploy') - matcher = self.m_request.put(expected_uri, json={}) - - dry_run = True - - self.client.redeploy_changes(env_id, dry_run=dry_run) - self.check_deploy_redeploy_changes(dry_run, matcher) - - @mock.patch.object(task_object.DeployTask, 'init_with_data') - def test_env_redeploy_noop_run(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, - '/changes/redeploy') - matcher = self.m_request.put(expected_uri, json={}) - - noop_run = True - - self.client.redeploy_changes(env_id, noop_run=noop_run) - self.check_deploy_redeploy_changes(noop_run, matcher, mode='noop_run') - - def test_env_reset(self): - env_id = 42 - force = False - expected_uri = self.get_object_uri(self.res_uri, env_id, '/reset/') - - matcher = self.m_request.put(expected_uri, json=utils.get_fake_task()) - - self.client.reset(env_id, force=force) - - self.assertTrue(matcher.called) - self.assertEqual(matcher.last_request.qs['force'][0], str(int(force))) - - def test_env_reset_force(self): - env_id = 42 - force = True - expected_uri = self.get_object_uri(self.res_uri, env_id, '/reset/') - - matcher = self.m_request.put(expected_uri, json=utils.get_fake_task()) - - self.client.reset(env_id, force=force) - - self.assertTrue(matcher.called) - self.assertEqual(matcher.last_request.qs['force'][0], str(int(force))) - - @mock.patch.object(base_object.BaseObject, 'init_with_data') - def test_env_update(self, m_init): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id) - - get_matcher = self.m_request.get(expected_uri, json=self.fake_env) - upd_matcher = self.m_request.put(expected_uri, json=self.fake_env) - - self.client.update(env_id, name="new_name") - - self.assertTrue(expected_uri, get_matcher.called) - self.assertTrue(expected_uri, upd_matcher.called) - - req_data = upd_matcher.last_request.json() - self.assertEqual('new_name', req_data['name']) - - def test_env_update_wrong_attribute(self): - env_id = 42 - self.assertRaises(error.BadDataException, - self.client.update, env_id, id=43) - - def test_env_add_nodes(self): - nodes = [25, 26] - roles = ['cinder', 'compute'] - env_id = 42 - - expected_body = [] - for n in nodes: - expected_body.append({'id': n, 'roles': roles}) - - expected_uri = self.get_object_uri(self.res_uri, - env_id, '/assignment/') - - matcher = self.m_request.post(expected_uri, json={}) - - self.client.add_nodes(env_id, nodes, roles) - - self.assertTrue(matcher.called) - - for assignment in matcher.last_request.json(): - # Check whether all assignments are expected - self.assertIn(assignment, expected_body) - - @mock.patch.object(fuelversion_object.FuelVersion, 'get_feature_groups') - def test_env_spawn_vms(self, m_feature_groups): - env_id = 10 - expected_uri = '/api/v1/clusters/{0}/spawn_vms/'.format(env_id) - m_feature_groups.return_value = \ - utils.get_fake_fuel_version()['feature_groups'] - - matcher = self.m_request.put(expected_uri, json={}) - - self.client.spawn_vms(env_id) - - self.assertTrue(matcher.called) - - def test_env_stop(self): - env_id = 42 - expected_uri = self.get_object_uri(self.res_uri, env_id, - '/stop_deployment/') - - matcher = self.m_request.put(expected_uri, json=utils.get_fake_task()) - - self.client.stop(env_id) - - self.assertTrue(matcher.called) - - def test_env_remove_nodes_by_id(self): - nodes = [25, 26] - env_id = 42 - - expected_body = [] - for n in nodes: - expected_body.append({'id': n}) - - expected_uri = self.get_object_uri(self.res_uri, - env_id, '/unassignment/') - - matcher = self.m_request.post(expected_uri, json={}) - - self.client.remove_nodes(env_id, nodes=nodes) - - self.assertTrue(matcher.called) - - for unassignment in matcher.last_request.json(): - # Check whether all unassignments are expected - self.assertIn(unassignment, expected_body) - - def test_env_remove_nodes_all(self): - nodes = [24, 25, 26] - env_id = 42 - - expected_body = [] - for n in nodes: - expected_body.append({'id': n}) - - fake_nodes = [utils.get_fake_node(node_name='node_' + str(n), - node_id=n, - cluster=env_id) for n in nodes] - - expected_uri = self.get_object_uri(self.res_uri, - env_id, '/unassignment/') - matcher_get = self.m_request.get( - '/api/v1/nodes/?cluster_id={}'.format(env_id), - json=fake_nodes - ) - matcher_post = self.m_request.post(expected_uri, json={}) - self.client.remove_nodes(env_id) - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_post.called) - - for unassignment in matcher_post.last_request.json(): - # Check whether all unassignments are expected - self.assertIn(unassignment, expected_body) - - def test_env_deploy_nodes(self): - env_id = 42 - node_ids = [43, 44] - - expected_url = self.get_object_uri(self.res_uri, env_id, '/deploy/') - matcher = self.m_request.put(expected_url, json=utils.get_fake_task()) - - self.client.deploy_nodes(env_id, node_ids) - - self.assertTrue(matcher.called) - self.assertEqual([','.join(str(i) for i in node_ids)], - matcher.last_request.qs['nodes']) - - def test_env_deploy_nodes_force(self): - env_id = 42 - node_ids = [43, 44] - force = True - - expected_url = self.get_object_uri(self.res_uri, env_id, '/deploy/') - matcher = self.m_request.put(expected_url, json=utils.get_fake_task()) - - self.client.deploy_nodes(env_id, node_ids, force=force) - - self.assertTrue(matcher.called) - self.assertEqual([','.join(str(i) for i in node_ids)], - matcher.last_request.qs['nodes']) - self.assertEqual(matcher.last_request.qs['force'][0], str(int(force))) - - def test_env_deploy_nodes_noop_run(self): - env_id = 42 - node_ids = [43, 44] - noop_run = True - - expected_url = self.get_object_uri(self.res_uri, env_id, '/deploy/') - matcher = self.m_request.put(expected_url, json=utils.get_fake_task()) - - self.client.deploy_nodes(env_id, node_ids, noop_run=noop_run) - - self.assertTrue(matcher.called) - self.assertEqual([','.join(str(i) for i in node_ids)], - matcher.last_request.qs['nodes']) - self.assertEqual(matcher.last_request.qs['noop_run'][0], - str(int(noop_run))) - - def test_env_provision_nodes(self): - env_id = 42 - node_ids = [43, 44] - - expected_url = self.get_object_uri(self.res_uri, env_id, '/provision/') - matcher = self.m_request.put(expected_url, json=utils.get_fake_task()) - - self.client.provision_nodes(env_id, node_ids) - - self.assertTrue(matcher.called) - self.assertEqual([','.join(str(i) for i in node_ids)], - matcher.last_request.qs['nodes']) - - def test_env_network_verify(self): - env_id = 42 - fake_env = utils.get_fake_env(env_id=env_id) - test_conf = utils.get_fake_env_network_conf() - - env_uri = self.get_object_uri(self.res_uri, env_id) - download_uri = self.get_object_uri(self.res_uri, - env_id, - self.net_conf_uri) - verify_uri = self.get_object_uri(self.res_uri, - env_id, - self.net_verify_uri) - - m_get = self.m_request.get(env_uri, json=fake_env) - m_download = self.m_request.get(download_uri, json=test_conf) - m_verify = self.m_request.put(verify_uri, json=utils.get_fake_task()) - - self.client.verify_network(env_id) - - self.assertTrue(m_get.called) - self.assertTrue(m_download.called) - self.assertTrue(m_verify.called) - self.assertEqual(test_conf, m_verify.last_request.json()) - - def test_env_network_download(self): - env_id = 42 - fake_env = utils.get_fake_env(env_id=env_id) - env_uri = self.get_object_uri(self.res_uri, env_id) - download_uri = self.get_object_uri(self.res_uri, - env_id, - self.net_conf_uri) - test_conf = utils.get_fake_env_network_conf() - - m_get = self.m_request.get(env_uri, json=fake_env) - m_download = self.m_request.get(download_uri, json=test_conf) - - net_conf = self.client.get_network_configuration(env_id) - - self.assertEqual(test_conf, net_conf) - self.assertTrue(m_get.called) - self.assertTrue(m_download.called) - - def test_env_network_upload(self): - env_id = 42 - fake_env = utils.get_fake_env(env_id=env_id) - env_uri = self.get_object_uri(self.res_uri, env_id) - upload_uri = self.get_object_uri(self.res_uri, - env_id, - self.net_conf_uri) - test_conf = utils.get_fake_env_network_conf() - - m_get = self.m_request.get(env_uri, json=fake_env) - m_upload = self.m_request.put(upload_uri, json={}) - - self.client.set_network_configuration(env_id, test_conf) - - self.assertTrue(m_get.called) - self.assertTrue(m_upload.called) - self.assertEqual(test_conf, m_upload.last_request.json()) - - def test_env_settings_download(self): - env_id = 42 - download_uri = self.get_object_uri(self.res_uri, - env_id, - self.settings_uri) - test_settings = {'test-data': 42} - - m_download = self.m_request.get(download_uri, json=test_settings) - - settings = self.client.get_settings(env_id) - - self.assertEqual(test_settings, settings) - self.assertTrue(m_download.called) - - def test_env_settings_upload(self): - env_id = 42 - upload_uri = self.get_object_uri(self.res_uri, - env_id, - self.settings_uri) - test_settings = {'test-data': 42} - - m_upload = self.m_request.put(upload_uri, json={}) - - self.client.set_settings(env_id, test_settings) - - self.assertTrue(m_upload.called) - self.assertEqual(test_settings, m_upload.last_request.json()) - - def test_env_settings_upload_force(self): - env_id = 42 - upload_uri = self.get_object_uri(self.res_uri, - env_id, - self.settings_uri) - test_settings = {'test-data': 42} - - m_upload = self.m_request.put(upload_uri, json={}) - - self.client.set_settings(env_id, test_settings, force=True) - - self.assertTrue(m_upload.called) - self.assertEqual(test_settings, m_upload.last_request.json()) - self.assertEqual(['1'], m_upload.last_request.qs.get('force')) - - def test_delete_facts(self): - env_id = 42 - fact_type = 'deployment' - expected_uri = self.get_object_uri( - self.res_uri, - env_id, - '/orchestrator/{fact_type}/'.format(fact_type=fact_type)) - - matcher = self.m_request.delete(expected_uri, json={}) - self.client.delete_facts(env_id, fact_type) - self.assertTrue(matcher.called) - self.assertIsNone(matcher.last_request.body) - - def test_download_facts(self): - env_id = 42 - fact_type = 'deployment' - nodes = [2, 5] - expected_uri = self.get_object_uri( - self.res_uri, - env_id, - "/orchestrator/{fact_type}/?nodes={nodes}".format( - fact_type=fact_type, nodes=",".join(map(str, nodes)))) - fake_resp = {'foo': 'bar'} - - matcher = self.m_request.get(expected_uri, json=fake_resp) - facts = self.client.download_facts( - env_id, fact_type, nodes=nodes, default=False) - self.assertTrue(matcher.called) - self.assertIsNone(matcher.last_request.body) - self.assertEqual(facts, fake_resp) - - def test_upload_facts(self): - env_id = 42 - fact_type = 'deployment' - facts = {'foo': 'bar'} - expected_uri = self.get_object_uri( - self.res_uri, - env_id, - "/orchestrator/{fact_type}/".format(fact_type=fact_type)) - - matcher = self.m_request.put(expected_uri, json={}) - self.client.upload_facts(env_id, fact_type, facts) - self.assertTrue(matcher.called) - self.assertEqual(facts, matcher.last_request.json()) diff --git a/fuelclient/tests/unit/v2/lib/test_extension.py b/fuelclient/tests/unit/v2/lib/test_extension.py deleted file mode 100644 index 335a14f2..00000000 --- a/fuelclient/tests/unit/v2/lib/test_extension.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestExtensionFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestExtensionFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/extensions/'.format( - version=self.version) - self.res_env_uri = '/api/{version}/clusters/'.format( - version=self.version) - self.fake_ext = ['fake_ext1'] - self.fake_extensions = utils.get_fake_extensions(10) - self.fake_env_extensions = utils.get_fake_env_extensions() - - self.client = fuelclient.get_client('extension', self.version) - - def test_extension_list(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_extensions) - self.client.get_all() - - self.assertTrue(matcher.called) - - def test_env_extension_list(self): - env_id = 42 - expected_uri = self.get_object_uri(self.res_env_uri, env_id, - '/extensions/') - matcher = self.m_request.get(expected_uri, - json=self.fake_env_extensions) - extensions = self.client.get_by_id(env_id) - - self.assertTrue(matcher.called) - for ext in self.fake_env_extensions: - self.assertIn(ext, extensions['extensions']) - - def test_env_extension_enable(self): - env_id = 42 - fake_ext = ['enabled_fake_ext4'] - expected_uri = self.get_object_uri(self.res_env_uri, env_id, - '/extensions/') - put_matcher = self.m_request.put(expected_uri, - json=self.fake_env_extensions) - - self.client.enable_extensions(env_id, fake_ext) - - self.assertTrue(put_matcher.called) - self.assertIn(fake_ext[0], put_matcher.last_request.json()) - - def test_env_extension_disable(self): - env_id = 42 - expected_uri = self.get_object_uri( - self.res_env_uri, - env_id, - '/extensions/?extension_names={0}'.format( - ','.join(self.fake_env_extensions))) - - delete_matcher = self.m_request.delete(expected_uri, - complete_qs=True, - json=self.fake_env_extensions) - - self.client.disable_extensions(env_id, self.fake_env_extensions) - - self.assertTrue(delete_matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_fuel_version.py b/fuelclient/tests/unit/v2/lib/test_fuel_version.py deleted file mode 100644 index d18484bd..00000000 --- a/fuelclient/tests/unit/v2/lib/test_fuel_version.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestFuelVersionFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestFuelVersionFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/version/'.format(version=self.version) - - self.fake_version = utils.get_fake_fuel_version() - - self.client = fuelclient.get_client('fuel-version', self.version) - - def test_fuel_version(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_version) - - self.client.get_all() - - self.assertTrue(matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_health.py b/fuelclient/tests/unit/v2/lib/test_health.py deleted file mode 100644 index c9ebb4d4..00000000 --- a/fuelclient/tests/unit/v2/lib/test_health.py +++ /dev/null @@ -1,292 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 mock - -import fuelclient -from fuelclient.cli import error -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestHealthFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestHealthFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/ostf/' - self.fake_test_sets = utils.get_fake_test_sets(10) - self.fake_test_sets_items = utils.get_fake_test_set_items(10) - - self.client = fuelclient.get_client('health', self.version) - - def test_health_list_for_cluster(self): - cluster_id = 65 - expected_uri = self.res_uri + 'testsets/{0}/'.format(cluster_id) - matcher = self.m_request.get(expected_uri, json=self.fake_test_sets) - - data = self.client.get_all(cluster_id) - - self.assertTrue(matcher.called) - self.assertEqual(len(data), 10) - - def test_health_status_list(self): - expected_uri = self.res_uri + 'testruns/' - matcher = self.m_request.get(expected_uri, - json=self.fake_test_sets_items) - - data = self.client.get_status_all() - - self.assertTrue(matcher.called) - self.assertEqual(len(data), 10) - - def test_health_status_list_for_cluster(self): - cluster_id = 32 - expected_uri = self.res_uri + 'testruns/' - fake_test_sets_items = [ - utils.get_fake_test_set_item(testset_id=12, cluster_id=cluster_id), - utils.get_fake_test_set_item(testset_id=13, cluster_id=cluster_id), - utils.get_fake_test_set_item(testset_id=14, cluster_id=35) - ] - matcher = self.m_request.get(expected_uri, - json=fake_test_sets_items) - - data = self.client.get_status_all(cluster_id) - - self.assertTrue(matcher.called) - self.assertEqual(len(data), 2) - - def test_health_status_show(self): - testrun_id = 65 - cluster_id = 32 - fake_test_set_item = utils.get_fake_test_set_item( - testset_id=testrun_id, cluster_id=cluster_id) - expected_uri = self.get_object_uri(self.res_uri + 'testruns/', - testrun_id) - matcher = self.m_request.get(expected_uri, - json=fake_test_set_item) - - data = self.client.get_status_single(testrun_id) - - self.assertTrue(matcher.called) - self.assertEqual(testrun_id, data["id"]) - self.assertEqual(cluster_id, data["cluster_id"]) - - def test_health_status_show_non_existing_testrun(self): - testrun_id = 65 - expected_uri = self.get_object_uri(self.res_uri + 'testruns/', - testrun_id) - matcher = self.m_request.get(expected_uri, json={}) - - msg = "Test sets with id {id} does not exist".format(id=testrun_id) - self.assertRaisesRegexp(error.ActionException, - msg, - self.client.get_status_single, - testrun_id) - self.assertTrue(matcher.called) - - @mock.patch('fuelclient.objects.Environment') - def test_health_start(self, m_env_obj): - cluster_id = 32 - cluster_state = 'operational' - test_sets = ['fake_test_set1', 'fake_test_set2'] - expected_uri = self.res_uri + 'testruns/' - type(m_env_obj.return_value).status = mock.PropertyMock( - return_value=cluster_state) - type(m_env_obj.return_value).is_customized = mock.PropertyMock( - return_value=False) - expected_body = [ - {'testset': test_sets[0], - 'metadata': {'cluster_id': cluster_id, 'config': {}}}, - {'testset': test_sets[1], - 'metadata': {'cluster_id': cluster_id, 'config': {}}} - ] - matcher = self.m_request.post(expected_uri, json=expected_body) - - data = self.client.start(cluster_id, - ostf_credentials={}, - test_sets=test_sets, - force=False) - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - self.assertEqual(data, matcher.last_request.json()) - - @mock.patch('fuelclient.objects.Environment') - def test_health_start_fail_not_allowed_env_status(self, m_env_obj): - cluster_id = 32 - cluster_state = 'new' - test_sets = ['fake_test_set1', 'fake_test_set2'] - type(m_env_obj.return_value).status = mock.PropertyMock( - return_value=cluster_state) - - msg = ("Environment is not ready to run health check " - "because it is in '{0}' state.".format(cluster_state)) - self.assertRaisesRegexp(error.EnvironmentException, - msg, - self.client.start, - cluster_id, - ostf_credentials={}, - test_sets=test_sets, - force=False) - - @mock.patch('fuelclient.objects.Environment') - def test_health_start_not_allowed_env_status_w_force(self, m_env_obj): - cluster_id = 32 - cluster_state = 'new' - test_sets = ['fake_test_set1', 'fake_test_set2'] - expected_uri = self.res_uri + 'testruns/' - type(m_env_obj.return_value).status = mock.PropertyMock( - return_value=cluster_state) - type(m_env_obj.return_value).is_customized = mock.PropertyMock( - return_value=False) - expected_body = [ - {'testset': test_sets[0], - 'metadata': {'cluster_id': cluster_id, 'config': {}}}, - {'testset': test_sets[1], - 'metadata': {'cluster_id': cluster_id, 'config': {}}} - ] - matcher = self.m_request.post(expected_uri, json=expected_body) - - data = self.client.start(cluster_id, - ostf_credentials={}, - test_sets=test_sets, - force=True) - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - self.assertEqual(data, matcher.last_request.json()) - - @mock.patch('fuelclient.objects.Environment') - def test_health_start_fail_customized_env(self, m_env_obj): - cluster_id = 32 - cluster_state = 'operational' - is_customized = True - test_sets = ['fake_test_set1', 'fake_test_set2'] - type(m_env_obj.return_value).status = mock.PropertyMock( - return_value=cluster_state) - type(m_env_obj.return_value).is_customized = mock.PropertyMock( - return_value=is_customized) - msg = ("Environment deployment facts were updated. " - "Health check is likely to fail because of that.") - self.assertRaisesRegexp(error.EnvironmentException, - msg, - self.client.start, - cluster_id, - ostf_credentials={}, - test_sets=test_sets, - force=False) - - @mock.patch('fuelclient.objects.Environment') - def test_health_start_customized_env_w_force(self, m_env_obj): - cluster_id = 32 - cluster_state = 'operational' - is_customized = True - test_sets = ['fake_test_set1', 'fake_test_set2'] - expected_uri = self.res_uri + 'testruns/' - type(m_env_obj.return_value).status = mock.PropertyMock( - return_value=cluster_state) - type(m_env_obj.return_value).is_customized = mock.PropertyMock( - return_value=is_customized) - expected_body = [ - {'testset': test_sets[0], - 'metadata': {'cluster_id': cluster_id, 'config': {}}}, - {'testset': test_sets[1], - 'metadata': {'cluster_id': cluster_id, 'config': {}}} - ] - matcher = self.m_request.post(expected_uri, json=expected_body) - - data = self.client.start(cluster_id, - ostf_credentials={}, - test_sets=test_sets, - force=True) - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - self.assertEqual(data, matcher.last_request.json()) - - @mock.patch('fuelclient.objects.Environment') - def test_health_start_w_ostf_credentials(self, m_env_obj): - cluster_id = 32 - cluster_state = 'operational' - is_customized = False - test_sets = ['fake_test_set1', 'fake_test_set2'] - ostf_credentials = { - 'username': 'admin', - 'password': 'admin', - 'tenant': 'admin' - } - expected_uri = self.res_uri + 'testruns/' - type(m_env_obj.return_value).status = mock.PropertyMock( - return_value=cluster_state) - type(m_env_obj.return_value).is_customized = mock.PropertyMock( - return_value=is_customized) - expected_body = [ - {'testset': test_sets[0], - 'metadata': { - 'ostf_os_access_creds': - {'ostf_os_username': 'admin', - 'ostf_os_tenant_name': 'admin', - 'ostf_os_password': 'admin'}, - 'cluster_id': cluster_id, - 'config': {}}}, - {'testset': test_sets[1], - 'metadata': { - 'ostf_os_access_creds': - {'ostf_os_username': 'admin', - 'ostf_os_tenant_name': 'admin', - 'ostf_os_password': 'admin'}, - 'cluster_id': cluster_id, - 'config': {}}} - ] - - matcher = self.m_request.post(expected_uri, json=expected_body) - - data = self.client.start(cluster_id, - ostf_credentials=ostf_credentials, - test_sets=test_sets, - force=False) - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - self.assertEqual(data, matcher.last_request.json()) - - def test_health_stop_action(self): - testrun_id = 65 - cluster_id = 32 - expected_uri = self.res_uri + 'testruns/' - fake_test_set_item = utils.get_fake_test_set_item( - testset_id=testrun_id, cluster_id=cluster_id) - matcher = self.m_request.put(expected_uri, - json=[fake_test_set_item]) - - data = self.client.action(testrun_id, action_status='stopped') - - self.assertTrue(matcher.called) - self.assertEqual(testrun_id, data["id"]) - self.assertEqual(cluster_id, data["cluster_id"]) - - def test_health_restart_action(self): - testrun_id = 65 - cluster_id = 32 - expected_uri = self.res_uri + 'testruns/' - fake_test_set_item = utils.get_fake_test_set_item( - testset_id=testrun_id, cluster_id=cluster_id) - matcher = self.m_request.put(expected_uri, - json=[fake_test_set_item]) - - data = self.client.action(testrun_id, action_status='restarted') - - self.assertTrue(matcher.called) - self.assertEqual(testrun_id, data["id"]) - self.assertEqual(cluster_id, data["cluster_id"]) diff --git a/fuelclient/tests/unit/v2/lib/test_network_group.py b/fuelclient/tests/unit/v2/lib/test_network_group.py deleted file mode 100644 index c3f6b22a..00000000 --- a/fuelclient/tests/unit/v2/lib/test_network_group.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright 2015 Mirantis, 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 fuelclient -from fuelclient.cli import error -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestNetworkGroupFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestNetworkGroupFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/networks/'.format(version=self.version) - - self.fake_network_group = utils.get_fake_network_group() - self.fake_network_groups = [utils.get_fake_network_group() - for i in range(10)] - - self.client = fuelclient.get_client('network-group') - - def test_network_group_list(self): - matcher = self.m_request.get( - self.res_uri, json=self.fake_network_groups) - - self.client.get_all() - self.assertTrue(matcher.called) - - def test_network_group_show(self): - expected_fields_names = ( - 'id', - 'name', - 'vlan_start', - 'cidr', - 'gateway', - 'group_id', - 'meta' - ) - net_id = 42 - uri = self.get_object_uri(self.res_uri, net_id) - - matcher = self.m_request.get( - uri, json=self.fake_network_group) - - data = self.client.get_by_id(net_id) - - self.assertTrue(matcher.called) - self.assertTrue(all(f in data for f - in expected_fields_names)) - - def test_network_group_create(self): - fake_ng = self.fake_network_group - matcher = self.m_request.post(self.res_uri, json=fake_ng) - - self.client.create( - name=fake_ng['name'], - release=fake_ng['release'], - vlan=fake_ng['vlan_start'], - cidr=fake_ng['cidr'], - gateway=fake_ng['gateway'], - group_id=fake_ng['group_id'], - meta=fake_ng['meta'], - ) - - req_data = matcher.last_request.json() - - self.assertTrue(matcher.called) - - self.assertEqual(req_data['name'], fake_ng['name']) - self.assertEqual(req_data['release'], fake_ng['release']) - self.assertEqual(req_data['vlan_start'], fake_ng['vlan_start']) - self.assertEqual(req_data['meta']['notation'], - fake_ng['meta']['notation']) - - def test_network_group_update(self): - net_id = 42 - uri = self.get_object_uri(self.res_uri, net_id) - - get_matcher = self.m_request.get(uri, json=self.fake_network_group) - put_matcher = self.m_request.put(uri, json=self.fake_network_group) - - self.client.update(net_id, name='new_name') - - self.assertTrue(get_matcher.called) - self.assertTrue(put_matcher.called) - - req_data = put_matcher.last_request.json() - self.assertEqual('new_name', req_data['name']) - - def test_network_group_update_wrong_attribute(self): - net_id = 42 - self.assertRaises(error.BadDataException, - self.client.update, net_id, vlan_start=42) - - def test_network_group_delete(self): - env_id = 42 - uri = self.get_object_uri(self.res_uri, env_id) - - matcher = self.m_request.delete(uri, json={}) - - self.client.delete_by_id(env_id) - - self.assertTrue(matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_network_template.py b/fuelclient/tests/unit/v2/lib/test_network_template.py deleted file mode 100644 index 1acf44d8..00000000 --- a/fuelclient/tests/unit/v2/lib/test_network_template.py +++ /dev/null @@ -1,78 +0,0 @@ -# -# Copyright 2015 Mirantis, 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 mock -import yaml - -from oslo_serialization import jsonutils as json - -import fuelclient -from fuelclient.tests.unit.common import \ - test_network_template as common_net_template -from fuelclient.tests.unit.v2.lib import test_api - - -class TestNetworkTemplateFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestNetworkTemplateFacade, self).setUp() - - self.version = 'v1' - self.env_id = 42 - self.res_uri = ( - '/api/{version}/clusters/{env_id}' - '/network_configuration/template'.format( - version=self.version, env_id=self.env_id)) - - self.client = fuelclient.get_client('environment', self.version) - - def test_network_template_upload(self): - expected_body = json.loads(common_net_template.JSON_TEMPLATE) - matcher = self.m_request.put( - self.res_uri, json=expected_body) - - m_open = mock.mock_open(read_data=common_net_template.YAML_TEMPLATE) - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.upload_network_template( - self.env_id, - 'fake_network_template_1.yaml' - ) - - m_open.assert_called_with('fake_network_template_1.yaml', 'r') - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - - def test_network_template_download(self): - expected_body = json.loads(common_net_template.JSON_TEMPLATE) - matcher = self.m_request.get(self.res_uri, json=expected_body) - - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.download_network_template(self.env_id) - - self.assertTrue(matcher.called) - - written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0]) - expected_yaml = yaml.safe_load(common_net_template.YAML_TEMPLATE) - self.assertEqual(written_yaml, expected_yaml) - - def test_network_template_delete(self): - matcher = self.m_request.delete(self.res_uri, json={}) - - self.client.delete_network_template(self.env_id) - - self.assertTrue(matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_node.py b/fuelclient/tests/unit/v2/lib/test_node.py deleted file mode 100644 index 68f06094..00000000 --- a/fuelclient/tests/unit/v2/lib/test_node.py +++ /dev/null @@ -1,561 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 mock -import os -import yaml - -import fuelclient -from fuelclient.cli import error -from fuelclient.cli import serializers -from fuelclient.objects import base as base_object -from fuelclient.objects import fuelversion as fuelversion_object -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestNodeFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestNodeFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/nodes/'.format(version=self.version) - - self.fake_node = utils.get_fake_node() - self.fake_nodes = [utils.get_fake_node() for _ in range(10)] - - self.client = fuelclient.get_client('node', self.version) - - def test_node_list(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_nodes) - self.client.get_all() - - self.assertTrue(matcher.called) - - def test_node_list_with_labels(self): - labels = ['key1'] - fake_nodes = [ - utils.get_fake_node( - node_name='node_1', labels={'key1': 'val1'}), - utils.get_fake_node( - node_name='node_2', labels={'key2': 'val2'}), - utils.get_fake_node( - node_name='node_3', labels={'key1': 'val2', 'key3': 'val3'}) - ] - - matcher_get = self.m_request.get(self.res_uri, json=fake_nodes) - - data = self.client.get_all(labels=labels) - - self.assertTrue(matcher_get.called) - self.assertEqual(len(data), 2) - self.assertEqual(data[0]['name'], 'node_1') - self.assertEqual(data[1]['name'], 'node_3') - - def test_node_show(self): - node_id = 42 - expected_uri = self.get_object_uri(self.res_uri, node_id) - - matcher = self.m_request.get(expected_uri, json=self.fake_node) - - self.client.get_by_id(node_id) - - self.assertTrue(matcher.called) - - @mock.patch.object(fuelversion_object.FuelVersion, 'get_feature_groups') - def test_node_vms_list(self, m_feature_groups): - node_id = 42 - expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id) - m_feature_groups.return_value = \ - utils.get_fake_fuel_version()['feature_groups'] - - fake_vms = [{'id': 1, 'opt2': 'val2'}, - {'id': 2, 'opt4': 'val4'}] - matcher = self.m_request.get(expected_uri, json=fake_vms) - - self.client.get_node_vms_conf(node_id) - - self.assertTrue(matcher.called) - - @mock.patch.object(fuelversion_object.FuelVersion, 'get_feature_groups') - def test_node_vms_create(self, m_feature_groups): - config = [{'id': 1, 'opt2': 'val2'}, - {'id': 2, 'opt4': 'val4'}] - node_id = 42 - m_feature_groups.return_value = \ - utils.get_fake_fuel_version()['feature_groups'] - - expected_uri = "/api/v1/nodes/{0}/vms_conf/".format(node_id) - expected_body = {'vms_conf': config} - - matcher = self.m_request.put(expected_uri, json=expected_body) - - self.client.node_vms_create(node_id, config) - - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - - def test_node_set_hostname(self): - node_id = 42 - hostname = 'test-name' - data = {"hostname": hostname} - expected_uri = self.get_object_uri(self.res_uri, node_id) - - matcher = self.m_request.put(expected_uri, json=data) - - self.client.update(node_id, **data) - - self.assertTrue(matcher.called) - self.assertEqual(data, matcher.last_request.json()) - - def test_get_all_labels_for_all_nodes(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_nodes) - self.client.get_all_labels_for_nodes() - - self.assertTrue(matcher.called) - - def test_set_labels_for_all_nodes(self): - labels = ['key_1=val_1', 'key_2=val_2', 'key_3 = val_4'] - data = {'labels': { - 'key_1': 'val_1', - 'key_2': 'val_2', - 'key_3': 'val_4' - }} - - expected_uri = self.get_object_uri(self.res_uri, 42) - - matcher_get = self.m_request.get(self.res_uri, json=self.fake_nodes) - matcher_put = self.m_request.put(expected_uri, json=data) - - self.client.set_labels_for_nodes(labels=labels) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertEqual(data, matcher_put.last_request.json()) - - def test_set_labels_for_specific_nodes(self): - labels = ['key_1=val_1', 'key_2=val_2', 'key_3 = val_4'] - node_ids = ['42'] - data = {'labels': { - 'key_1': 'val_1', - 'key_2': 'val_2', - 'key_3': 'val_4' - }} - expected_uri = self.get_object_uri(self.res_uri, 42) - - matcher_get = self.m_request.get(expected_uri, json=self.fake_node) - matcher_put = self.m_request.put(expected_uri, json=data) - - self.client.set_labels_for_nodes(labels=labels, node_ids=node_ids) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertEqual(data, matcher_put.last_request.json()) - - def test_set_labels_with_empty_key(self): - labels = ['key_1=val_1', ' = val_2', 'key_3 = '] - node_ids = ['42'] - - msg = 'Wrong label "{0}" was provided. Label key couldn\'t ' \ - 'be an empty string.'.format(labels[1]) - with self.assertRaisesRegexp(error.LabelEmptyKeyError, msg): - self.client.set_labels_for_nodes(labels=labels, node_ids=node_ids) - - def test_delete_specific_labels_for_all_nodes(self): - labels = ['key_1', ' key_3 '] - data = {'labels': {'key_2': None}} - expected_uri = self.get_object_uri(self.res_uri, 42) - - matcher_get = self.m_request.get(self.res_uri, json=self.fake_nodes) - matcher_put = self.m_request.put(expected_uri, json=data) - - self.client.delete_labels_for_nodes(labels=labels) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertEqual(data, matcher_put.last_request.json()) - - def test_delete_specific_labels_for_specific_nodes(self): - labels = ['key_2'] - node_ids = ['42'] - data = {'labels': {'key_1': 'val_1', 'key_3': 'val_3'}} - expected_uri = self.get_object_uri(self.res_uri, 42) - - matcher_get = self.m_request.get(expected_uri, json=self.fake_node) - matcher_put = self.m_request.put(expected_uri, json=data) - - self.client.delete_labels_for_nodes(labels=labels, node_ids=node_ids) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertEqual(data, matcher_put.last_request.json()) - - def test_delete_all_labels_for_all_nodes(self): - data = {'labels': {}} - expected_uri = self.get_object_uri(self.res_uri, 42) - - matcher_get = self.m_request.get(self.res_uri, json=self.fake_nodes) - matcher_put = self.m_request.put(expected_uri, json=data) - - self.client.delete_labels_for_nodes(labels=None) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertEqual(data, matcher_put.last_request.json()) - - def test_delete_all_labels_for_specific_nodes(self): - node_ids = ['42'] - data = {'labels': {}} - expected_uri = self.get_object_uri(self.res_uri, 42) - - matcher_get = self.m_request.get(expected_uri, json=self.fake_node) - matcher_put = self.m_request.put(expected_uri, json=data) - - self.client.delete_labels_for_nodes(labels=None, node_ids=node_ids) - - self.assertTrue(matcher_get.called) - self.assertTrue(matcher_put.called) - self.assertEqual(data, matcher_put.last_request.json()) - - def test_delete_labels_by_value(self): - labels = ['key_1=val_1', 'key_3=anothervalue', 'key_2'] - node_ids = ['42'] - result_labels = {'labels': {'key_3': 'val_3'}} - expected_uri = self.get_object_uri(self.res_uri, 42) - - self.m_request.get(expected_uri, json=self.fake_node) - matcher_put = self.m_request.put(expected_uri, json=self.fake_node) - - self.client.delete_labels_for_nodes( - labels=labels, node_ids=node_ids) - - self.assertTrue(matcher_put.called) - self.assertEqual(result_labels, matcher_put.last_request.json()) - - def test_delete_labels_by_value_with_whitespace(self): - labels = ['key_1 =val_1', 'key_3= anothervalue', 'key_2'] - node_ids = ['42'] - result_labels = {'labels': {'key_3': 'val_3'}} - expected_uri = self.get_object_uri(self.res_uri, 42) - - self.m_request.get(expected_uri, json=self.fake_node) - matcher_put = self.m_request.put(expected_uri, json=self.fake_node) - - self.client.delete_labels_for_nodes( - labels=labels, node_ids=node_ids) - - self.assertTrue(matcher_put.called) - self.assertEqual(result_labels, matcher_put.last_request.json()) - - def test_get_name_and_value_from_labels(self): - for label in ( - 'key=value', - ' key =value', - 'key= value ', - ' key = value ', - ): - name, value, has_separator = self.client._split_label(label) - self.assertEqual(name, 'key') - self.assertEqual(value, 'value') - self.assertTrue(has_separator) - - def test_get_name_and_empty_value_from_lables(self): - for label in ( - 'key=', - ' key =', - 'key= ', - ' key = ', - ): - name, value, has_separator = self.client._split_label(label) - self.assertEqual(name, 'key') - self.assertIsNone(value) - self.assertTrue(has_separator) - - def test_get_name_without_separator(self): - for label in ( - 'key', - ' key ', - ): - name, value, has_separator = self.client._split_label(label) - self.assertEqual(name, 'key') - self.assertIsNone(value) - self.assertFalse(has_separator) - - def test_label_with_many_separators(self): - label = 'key1= key2 = val2' - name, value, has_separator = self.client._split_label(label) - self.assertEqual(name, 'key1') - self.assertEqual(value, 'key2 = val2') - self.assertTrue(has_separator) - - def test_labels_after_delete(self): - all_labels = { - 'label_A': 'A', - 'label_B': None, - 'label_C': 'C', - 'label_D': None, - } - expected_labels = { - 'label_A': 'A', - 'label_D': None, - } - - for labels_to_delete in ( - ('label_B', 'label_C'), - (' label_B', 'label_C '), - ('label_B', 'label_C ', 'unknown_label'), - ('label_A = trololo', 'label_B=', 'label_C =C', 'label_D=value') - ): - result = self.client._labels_after_delete( - all_labels, labels_to_delete) - self.assertEqual(result, expected_labels) - - @mock.patch.object(base_object.BaseObject, 'init_with_data') - def test_node_update(self, m_init): - node_id = 42 - expected_uri = self.get_object_uri(self.res_uri, node_id) - - get_matcher = self.m_request.get(expected_uri, json=self.fake_node) - upd_matcher = self.m_request.put(expected_uri, json=self.fake_node) - - self.client.update(node_id, hostname="new-name") - - self.assertTrue(expected_uri, get_matcher.called) - self.assertTrue(expected_uri, upd_matcher.called) - - req_data = upd_matcher.last_request.json() - self.assertEqual('new-name', req_data['hostname']) - - def test_node_update_wrong_attribute(self): - node_id = 42 - self.assertRaises(error.BadDataException, - self.client.update, node_id, status=42) - - @mock.patch('fuelclient.objects.node.os.mkdir', mock.Mock()) - def test_node_attributes_download(self): - node_id = 42 - expected_uri = self.get_object_uri( - self.res_uri, node_id, '/attributes/') - fake_attributes = { - 'attribute_name': 'attribute_value' - } - - m_get = self.m_request.get(expected_uri, json=fake_attributes) - - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.download_attributes(node_id, directory='/fake/dir') - - self.assertTrue(m_get.called) - m_open.assert_called_once_with( - '/fake/dir/node_{0}/attributes.yaml'.format(node_id), mock.ANY) - serializer = serializers.Serializer() - m_open().write.assert_called_once_with( - serializer.serialize(fake_attributes)) - - def test_node_disks_upload(self): - node_id = 42 - new_disks = {'test_key': u'test ☃ value'} - - node_uri = self.get_object_uri(self.res_uri, node_id) - disks_uri = os.path.join(node_uri, 'disks/') - - get_matcher = self.m_request.get(node_uri, json=self.fake_node) - upd_matcher = self.m_request.put(disks_uri, json={}) - - self.client.set_disks(node_id, new_disks) - - self.assertTrue(node_uri, get_matcher.called) - self.assertTrue(disks_uri, upd_matcher.called) - - req_data = upd_matcher.last_request.json() - self.assertEqual(new_disks, req_data) - - def test_node_disks_download(self): - node_id = 42 - fake_resp = {'test_key': u'test ☃ value'} - - node_uri = self.get_object_uri(self.res_uri, node_id) - disks_uri = os.path.join(node_uri, 'disks/') - - node_matcher = self.m_request.get(node_uri, json=self.fake_node) - disks_matcher = self.m_request.get(disks_uri, json=fake_resp) - - disks = self.client.get_disks(node_id) - - self.assertTrue(node_uri, node_matcher.called) - self.assertTrue(disks_uri, disks_matcher.called) - - self.assertEqual(disks, fake_resp) - - def test_node_disks_defaults(self): - node_id = 42 - fake_resp = {'test_key': u'test ☃ value'} - - node_uri = self.get_object_uri(self.res_uri, node_id) - disks_uri = os.path.join(node_uri, 'disks/defaults') - - node_matcher = self.m_request.get(node_uri, json=self.fake_node) - disks_matcher = self.m_request.get(disks_uri, json=fake_resp) - - disks = self.client.get_default_disks(node_id) - - self.assertTrue(node_uri, node_matcher.called) - self.assertTrue(disks_uri, disks_matcher.called) - - self.assertEqual(disks, fake_resp) - - @mock.patch('fuelclient.objects.node.os.path.exists', - mock.Mock(return_value=True)) - def test_node_attribute_upload(self): - node_id = 42 - expected_uri = self.get_object_uri( - self.res_uri, node_id, '/attributes/') - fake_attributes = { - 'attribute_name': 'attribute_value' - } - - m_put = self.m_request.put(expected_uri, json=fake_attributes) - - m_open = mock.mock_open(read_data=yaml.safe_dump(fake_attributes)) - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.upload_attributes(node_id, directory='/fake/dir') - - self.assertTrue(m_put.called) - m_open.assert_called_once_with( - '/fake/dir/node_{0}/attributes.yaml'.format(node_id), mock.ANY) - self.assertEqual(m_put.last_request.json(), fake_attributes) - m_open().read.assert_called_once_with() - - def test_node_interfaces_upload(self): - node_id = 42 - new_interfaces = {'test_key': u'test ☃ value'} - - node_uri = self.get_object_uri(self.res_uri, node_id) - interfaces_uri = os.path.join(node_uri, 'interfaces/') - - get_matcher = self.m_request.get(node_uri, json=self.fake_node) - upd_matcher = self.m_request.put(interfaces_uri, json={}) - - self.client.set_interfaces(node_id, new_interfaces) - - self.assertTrue(node_uri, get_matcher.called) - self.assertTrue(interfaces_uri, upd_matcher.called) - - req_data = upd_matcher.last_request.json() - self.assertEqual(new_interfaces, req_data) - - def test_node_interfaces_download(self): - node_id = 42 - fake_resp = {'test_key': u'test ☃ value'} - - node_uri = self.get_object_uri(self.res_uri, node_id) - interfaces_uri = os.path.join(node_uri, 'interfaces/') - - node_matcher = self.m_request.get(node_uri, json=self.fake_node) - interfaces_matcher = self.m_request.get(interfaces_uri, json=fake_resp) - - interfaces = self.client.get_interfaces(node_id) - - self.assertTrue(node_uri, node_matcher.called) - self.assertTrue(interfaces_uri, interfaces_matcher.called) - - self.assertEqual(interfaces, fake_resp) - - def test_node_interfaces_default(self): - node_id = 42 - fake_resp = {'test_key': u'test ☃ value'} - - node_uri = self.get_object_uri(self.res_uri, node_id) - interfaces_uri = os.path.join(node_uri, - 'interfaces/default_assignment') - - node_matcher = self.m_request.get(node_uri, json=self.fake_node) - interfaces_matcher = self.m_request.get(interfaces_uri, json=fake_resp) - - interfaces = self.client.get_default_interfaces(node_id) - - self.assertTrue(node_uri, node_matcher.called) - self.assertTrue(interfaces_uri, interfaces_matcher.called) - - self.assertEqual(interfaces, fake_resp) - - def test_undiscover_nodes_by_id_force(self): - node_id = 42 - expected_uri = '/api/v1/nodes/?ids={node_id}'.format(node_id=node_id) - request_url = self.get_object_uri(self.res_uri, node_id) - - node_matcher = self.m_request.get(request_url, json=self.fake_node) - matcher = self.m_request.delete(expected_uri, json={}) - - self.client.undiscover_nodes(node_id=node_id, force=True) - - self.assertTrue(matcher.called) - self.assertTrue(node_matcher.called) - self.assertEqual([str(node_id)], matcher.last_request.qs.get('ids')) - - def test_undiscover_nodes_by_id(self): - node_id = 42 - expected_uri = self.get_object_uri(self.res_uri, node_id) - node_matcher = self.m_request.get(expected_uri, json=self.fake_node) - - self.assertRaises(error.ActionException, - self.client.undiscover_nodes, - node_id=node_id, force=False) - self.assertTrue(node_matcher.called) - - def test_undiscover_nodes_by_env_force(self): - env_id = 24 - node_ids = ['42', '43', '44'] - expected_uri = '/api/v1/nodes/?ids={node_ids}'.format( - node_ids=','.join(node_ids)) - fake_nodes = [utils.get_fake_node(node_name='node_' + n_id, - node_id=n_id, - cluster=env_id) for n_id in node_ids] - - nodes_matcher = self.m_request.get(self.res_uri, json=fake_nodes) - matcher = self.m_request.delete(expected_uri, json={}) - - self.client.undiscover_nodes(env_id=env_id, node_id=None, force=True) - - self.assertTrue(matcher.called) - self.assertTrue(nodes_matcher.called) - self.assertEqual([','.join(node_ids)], - matcher.last_request.qs.get('ids')) - - def test_undiscover_nodes_by_env(self): - env_id = 24 - node_ids = ['42', '43', '44'] - fake_nodes = [utils.get_fake_node(node_name='node_' + n_id, - node_id=n_id, - cluster=env_id) for n_id in node_ids] - nodes_matcher = self.m_request.get(self.res_uri, json=fake_nodes) - - self.assertRaises(error.ActionException, - self.client.undiscover_nodes, - env_id=env_id, node_id=None, force=False) - self.assertTrue(nodes_matcher.called) - - def test_undiscover_nodes_w_wrong_params(self): - env_id = None - node_id = None - - self.assertRaises(ValueError, - self.client.undiscover_nodes, - env_id=env_id, node_id=node_id, force=False) diff --git a/fuelclient/tests/unit/v2/lib/test_openstack_config.py b/fuelclient/tests/unit/v2/lib/test_openstack_config.py deleted file mode 100644 index 7108239f..00000000 --- a/fuelclient/tests/unit/v2/lib/test_openstack_config.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright 2016 Mirantis, 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 mock -import yaml - -import fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestOpenstackConfigClient(test_api.BaseLibTest): - - def setUp(self): - super(TestOpenstackConfigClient, self).setUp() - - self.version = 'v1' - self.uri = '/api/{version}/openstack-config/'.format( - version=self.version) - - self.client = fuelclient.get_client('openstack-config', self.version) - - def test_config_list_for_cluster(self): - cluster_id = 1 - fake_configs = [ - utils.get_fake_openstack_config(cluster_id=cluster_id) - ] - - uri = self.uri + '?cluster_id={0}&is_active=True'.format(cluster_id) - m_get = self.m_request.get(uri, complete_qs=True, json=fake_configs) - data = self.client.get_filtered(cluster_id=1) - - self.assertTrue(m_get.called) - self.assertEqual(data[0]['cluster_id'], cluster_id) - - def test_config_list_for_node(self): - cluster_id = 1 - fake_configs = [ - utils.get_fake_openstack_config( - cluster_id=cluster_id, node_id=22), - ] - - uri = self.uri + '?cluster_id={0}&node_ids=22' \ - '&is_active=True'.format(cluster_id) - m_get = self.m_request.get(uri, complete_qs=True, json=fake_configs) - data = self.client.get_filtered(cluster_id=1, node_ids=[22]) - - self.assertTrue(m_get.called) - self.assertEqual(data[0]['cluster_id'], cluster_id) - - def test_config_list_for_multinode(self): - cluster_id = 1 - fake_configs = [ - utils.get_fake_openstack_config( - cluster_id=cluster_id, node_id=22), - utils.get_fake_openstack_config( - cluster_id=cluster_id, node_id=44), - ] - - uri = self.uri + '?cluster_id={0}&node_ids=22,44' \ - '&is_active=True'.format(cluster_id) - m_get = self.m_request.get(uri, complete_qs=True, json=fake_configs) - data = self.client.get_filtered(cluster_id=1, node_ids=[22, 44]) - - self.assertTrue(m_get.called) - self.assertEqual(data[0]['cluster_id'], cluster_id) - - def test_config_download(self): - config_id = 42 - uri = self.uri + '{0}/'.format(42) - fake_config = utils.get_fake_openstack_config(id=config_id) - - m_get = self.m_request.get(uri, json=fake_config) - - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.download(config_id, '/path/to/config') - - self.assertTrue(m_get.called) - written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0]) - self.assertEqual(written_yaml, - {'configuration': fake_config['configuration']}) - - def test_config_upload(self): - cluster_id = 1 - fake_config = utils.get_fake_openstack_config( - cluster_id=cluster_id) - - m_post = self.m_request.post(self.uri, json=[fake_config]) - - m_open = mock.mock_open(read_data=yaml.safe_dump({ - 'configuration': fake_config['configuration'] - })) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True), \ - mock.patch('os.path.exists', mock.Mock(return_value=True)): - self.client.upload('/path/to/config', cluster_id) - - self.assertTrue(m_post.called) - body = m_post.last_request.json() - self.assertEqual(body['cluster_id'], cluster_id) - self.assertNotIn('node_ids', body) - self.assertNotIn('node_role', body) - - def test_config_upload_multinode(self): - cluster_id = 1 - fake_configs = [ - utils.get_fake_openstack_config( - cluster_id=cluster_id, node_id=42), - utils.get_fake_openstack_config( - cluster_id=cluster_id, node_id=44) - ] - - m_post = self.m_request.post(self.uri, json=fake_configs) - - m_open = mock.mock_open(read_data=yaml.safe_dump({ - 'configuration': fake_configs[0]['configuration'] - })) - with mock.patch( - 'fuelclient.cli.serializers.open', m_open, create=True), \ - mock.patch('os.path.exists', mock.Mock(return_value=True)): - self.client.upload( - '/path/to/config', cluster_id, node_ids=[42, 44]) - - self.assertTrue(m_post.called) - body = m_post.last_request.json() - self.assertEqual(body['cluster_id'], cluster_id) - self.assertEqual(body['node_ids'], [42, 44]) - self.assertNotIn('node_role', body) - - def test_config_delete(self): - config_id = 42 - uri = self.uri + '{0}/'.format(config_id) - fake_config = utils.get_fake_openstack_config(id=config_id) - - m_del = self.m_request.delete(uri, json=fake_config) - - self.client.delete(config_id) - self.assertTrue(m_del.called) diff --git a/fuelclient/tests/unit/v2/lib/test_plugins.py b/fuelclient/tests/unit/v2/lib/test_plugins.py deleted file mode 100644 index 24681f95..00000000 --- a/fuelclient/tests/unit/v2/lib/test_plugins.py +++ /dev/null @@ -1,170 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 json - -from mock import mock - -import fuelclient -from fuelclient.cli import error -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestPluginsFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestPluginsFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/plugins/'.format(version=self.version) - - self.fake_plugins = utils.get_fake_plugins(10) - - self.client = fuelclient.get_client('plugins', self.version) - - def test_plugins_list(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_plugins) - self.client.get_all() - self.assertTrue(self.res_uri, matcher.called) - - def test_sync_plugins(self): - expected_uri = '/api/{version}/plugins/sync/'.format( - version=self.version - ) - matcher = self.m_request.post(expected_uri, json={}) - self.client.sync(None) - self.assertTrue(matcher.called) - self.assertIsNone(matcher.last_request.body) - - def test_sync_plugins_empty_ids(self): - expected_uri = '/api/{version}/plugins/sync/'.format( - version=self.version - ) - matcher = self.m_request.post(expected_uri, json={}) - self.client.sync([]) - self.assertTrue(matcher.called) - self.assertEqual([], matcher.last_request.json()['ids']) - - def test_sync_specified_plugins(self): - expected_uri = '/api/{version}/plugins/sync/'.format( - version=self.version - ) - ids = [1, 2] - matcher = self.m_request.post(expected_uri, json={}) - self.client.sync(ids=ids) - self.assertTrue(matcher.called) - self.assertEqual(ids, matcher.last_request.json()['ids']) - - -class TestPluginInstallFacade(TestPluginsFacade): - - def setUp(self): - super(TestPluginInstallFacade, self).setUp() - - self.m_exec = mock.patch.object(fuelclient.utils, 'exec_cmd') - self.m_is_master = mock.patch('fuelclient.objects.plugins.IS_MASTER', - True) - self.m_meta = mock.patch.object(fuelclient.utils, - 'glob_and_parse_yaml', - return_value=self.fake_plugins) - - self.m_file_exists = mock.patch.object(fuelclient.utils, - 'file_exists', - return_value=True) - - def exec_install(self, force=False): - path = '/path/to/plugin.rpm' - - post_matcher = self.m_request.post(self.res_uri, json={}) - get_matcher = self.m_request.get(self.res_uri, json={}) - put_matcher = None - - fake_plugin = self.fake_plugins[0] - if force: - put_uri = '/api/{version}/plugins/{id}'.format( - version=self.version, - id=fake_plugin['id']) - put_matcher = self.m_request.put(put_uri, json={}) - post_matcher = self.m_request.post(self.res_uri, json={ - 'message': json.dumps({'id': fake_plugin['id']}) - }, status_code=409) - m_name = mock.patch.object(fuelclient.objects.plugins.PluginV2, - 'name_from_file', - return_value=fake_plugin['name']) - m_version = mock.patch.object(fuelclient.objects.plugins.PluginV2, - 'version_from_file', - return_value=fake_plugin['version']) - - with m_name, m_version, self.m_is_master, self.m_meta, self.m_exec,\ - self.m_file_exists: - self.client.install(path, force) - - self.assertTrue(get_matcher.called) - self.assertTrue(post_matcher.called) - self.assertEqual(fake_plugin, - json.loads(post_matcher.last_request.body)) - if force: - self.assertTrue(put_matcher.called) - self.assertEqual(fake_plugin, - json.loads(put_matcher.last_request.body)) - - def test_install_plugin(self): - - self.exec_install() - - def test_install_plugin_force(self): - self.exec_install(True) - - def test_install_plugin_fail_not_master(self): - self.m_is_master = mock.patch('fuelclient.objects.plugins.IS_MASTER', - False) - self.assertRaises(error.WrongEnvironmentError, self.exec_install) - - def test_install_plugin_fail_file_not_exists(self): - self.m_file_exists = mock.patch.object(fuelclient.utils, - 'file_exists', - return_value=False) - self.assertRaises(error.BadDataException, self.exec_install) - - -class TestPluginRemoveFacade(TestPluginsFacade): - - def setUp(self): - super(TestPluginRemoveFacade, self).setUp() - - self.m_exec = mock.patch.object(fuelclient.utils, 'exec_cmd') - self.m_is_master = mock.patch('fuelclient.objects.plugins.IS_MASTER', - True) - - def exec_remove(self): - fake_plugin = self.fake_plugins[0] - expected_uri = '/api/{version}/plugins/{id}'.format( - version=self.version, id=fake_plugin['id']) - del_matcher = self.m_request.delete(expected_uri, json={}) - get_matcher = self.m_request.get(self.res_uri, json=self.fake_plugins) - with self.m_is_master, self.m_exec: - self.client.remove(fake_plugin['name'], fake_plugin['version']) - self.assertTrue(get_matcher.called) - self.assertTrue(del_matcher.called) - self.assertIsNone(del_matcher.last_request.body) - - def test_remove_plugin(self): - self.exec_remove() - - def test_remove_plugin_fail_not_master(self): - self.m_is_master = mock.patch('fuelclient.objects.plugins.IS_MASTER', - False) - self.assertRaises(error.WrongEnvironmentError, self.exec_remove) diff --git a/fuelclient/tests/unit/v2/lib/test_release.py b/fuelclient/tests/unit/v2/lib/test_release.py deleted file mode 100644 index e6afa636..00000000 --- a/fuelclient/tests/unit/v2/lib/test_release.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock - -import fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestReleaseFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestReleaseFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/releases/'.format(version=self.version) - self.fake_releases = utils.get_fake_releases(10) - self.fake_release_components = utils.get_fake_release_components(10) - self.fake_attributes_metadata = utils.get_fake_attributes_metadata() - self.client = fuelclient.get_client('release', self.version) - - def test_release_list(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_releases) - self.client.get_all() - self.assertTrue(matcher.called) - - def test_release_repos_list(self): - release_id = 42 - expected_uri = self.get_object_uri(self.res_uri, release_id, - '/attributes_metadata') - matcher = self.m_request.get(expected_uri, - json=self.fake_attributes_metadata) - self.client.get_attributes_metadata_by_id(release_id) - self.assertTrue(matcher.called) - - def test_release_repos_update(self): - release_id = 42 - expected_uri = self.get_object_uri(self.res_uri, release_id, - '/attributes_metadata') - m_put = self.m_request.put(expected_uri, - json=self.fake_attributes_metadata) - - m_open = mock.mock_open(read_data=self.fake_attributes_metadata) - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.update_attributes_metadata_by_id( - release_id=release_id, - data=self.fake_attributes_metadata - ) - self.assertTrue(m_put.called) - self.assertEqual(m_put.last_request.json(), - self.fake_attributes_metadata) - - def test_release_component_list(self): - release_id = 42 - expected_uri = self.get_object_uri(self.res_uri, release_id, - '/components') - matcher = self.m_request.get(expected_uri, - json=self.fake_release_components) - self.client.get_components_by_id(release_id) - self.assertTrue(matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_role.py b/fuelclient/tests/unit/v2/lib/test_role.py deleted file mode 100644 index fcd83686..00000000 --- a/fuelclient/tests/unit/v2/lib/test_role.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestRoleFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestRoleFacade, self).setUp() - - self.version = 'v1' - self.role_name = 'fake_role' - self.fake_role = utils.get_fake_role(self.role_name) - self.fake_roles = utils.get_fake_roles(10) - - self.client = fuelclient.get_client('role', self.version) - - def get_uri(self, owner): - return '/api/{version}/{owner}/'.format(version=self.version, - owner=owner) - - def test_release_role_list(self): - owner, owner_id = 'releases', 42 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/') - matcher = self.m_request.get(expected_uri, json=self.fake_roles) - self.client.get_all(owner, owner_id) - - self.assertTrue(matcher.called) - - def test_cluster_role_list(self): - owner, owner_id = 'clusters', 42 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/') - matcher = self.m_request.get(expected_uri, json=self.fake_roles) - self.client.get_all(owner_type=owner, owner_id=owner_id) - - self.assertTrue(matcher.called) - - def test_release_role_download(self): - owner, owner_id = 'releases', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/{}/'.format(self.role_name)) - role_matcher = self.m_request.get(expected_uri, json=self.fake_role) - - role = self.client.get_one(owner, owner_id, self.role_name) - - self.assertTrue(expected_uri, role_matcher.called) - self.assertEqual(role, self.fake_role) - - def test_cluster_role_download(self): - owner, owner_id = 'clusters', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/{}/'.format(self.role_name)) - role_matcher = self.m_request.get(expected_uri, json=self.fake_role) - - role = self.client.get_one(owner, owner_id, self.role_name) - - self.assertTrue(expected_uri, role_matcher.called) - self.assertEqual(role, self.fake_role) - - def test_release_role_update(self): - owner, owner_id = 'releases', 45 - params = {"owner_type": owner, - "owner_id": owner_id, - "role_name": self.role_name} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/{}/'.format(self.role_name)) - upd_matcher = self.m_request.put(expected_uri, json=self.fake_role) - - self.client.update(self.fake_role, **params) - - self.assertTrue(upd_matcher.called) - self.assertEqual(self.fake_role, upd_matcher.last_request.json()) - - def test_cluster_role_update(self): - owner, owner_id = 'clusters', 45 - params = {"owner_type": owner, - "owner_id": owner_id, - "role_name": self.role_name} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/{}/'.format(self.role_name)) - upd_matcher = self.m_request.put(expected_uri, json=self.fake_role) - - self.client.update(self.fake_role, **params) - - self.assertTrue(upd_matcher.called) - self.assertEqual(self.fake_role, upd_matcher.last_request.json()) - - def test_release_role_create(self): - owner, owner_id = 'releases', 45 - params = {"owner_type": owner, - "owner_id": owner_id} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/') - post_matcher = self.m_request.post(expected_uri, json=self.fake_role) - - self.client.create(self.fake_role, **params) - - self.assertTrue(post_matcher.called) - self.assertEqual(self.fake_role, post_matcher.last_request.json()) - - def test_cluster_role_create(self): - owner, owner_id = 'clusters', 45 - params = {"owner_type": owner, - "owner_id": owner_id} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/') - post_matcher = self.m_request.post(expected_uri, json=self.fake_role) - - self.client.create(self.fake_role, **params) - - self.assertTrue(post_matcher.called) - self.assertEqual(self.fake_role, post_matcher.last_request.json()) - - def test_release_role_delete(self): - owner, owner_id = 'releases', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/{}/'.format(self.role_name)) - delete_matcher = self.m_request.delete(expected_uri, json={}) - - self.client.delete(owner, owner_id, self.role_name) - - self.assertTrue(delete_matcher.called) - - def test_cluster_role_delete(self): - owner, owner_id = 'clusters', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/roles/{}/'.format(self.role_name)) - delete_matcher = self.m_request.delete(expected_uri, json={}) - - self.client.delete(owner, owner_id, self.role_name) - - self.assertTrue(delete_matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_sequence.py b/fuelclient/tests/unit/v2/lib/test_sequence.py deleted file mode 100644 index 8cc40abb..00000000 --- a/fuelclient/tests/unit/v2/lib/test_sequence.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api - - -class TestDeploymentSequence(test_api.BaseLibTest): - - def setUp(self): - super(TestDeploymentSequence, self).setUp() - self.version = 'v1' - self.client = fuelclient.get_client('sequence', self.version) - self.env_id = 1 - self.sequence_body = { - 'id': 1, 'release_id': 1, 'name': 'test', - 'graphs': [{'type': 'graph1'}] - } - - def _check_sequence_object(self, sequence): - self.assertEqual(self.sequence_body, sequence) - - def test_create(self): - matcher_post = self.m_request.post( - '/api/v1/sequences/', json=self.sequence_body - ) - sequence = self.client.create(1, name='test', graph_types=['graph1']) - self.assertTrue(matcher_post.called) - self._check_sequence_object(sequence) - - def test_update(self): - matcher_put = self.m_request.put( - '/api/v1/sequences/1/', json=self.sequence_body - ) - sequence = self.client.update(1, name='test') - self.assertTrue(matcher_put.called) - self.assertEqual('{"name": "test"}', matcher_put.last_request.body) - self._check_sequence_object(sequence) - - def test_delete(self): - mathcher_delete = self.m_request.delete( - '/api/v1/sequences/1/', status_code=204 - ) - self.client.delete_by_id(1) - self.assertTrue(mathcher_delete.called) - - def test_get_one(self): - matcher_get = self.m_request.get( - '/api/v1/sequences/1/', json=self.sequence_body - ) - sequence = self.client.get_by_id(1) - self.assertTrue(matcher_get.called) - self.assertEqual('test', sequence['name']) - self.assertEqual('graph1', sequence['graphs']) - - def test_get_all(self): - matcher_get = self.m_request.get( - '/api/v1/sequences/?release=1', json=[self.sequence_body] - ) - sequences = self.client.get_all(release=1) - self.assertTrue(matcher_get.called) - self.assertEqual(1, len(sequences)) - self._check_sequence_object(sequences[0]) - - def test_execute(self): - self.m_request.get('/api/v1/nodes/?cluster_id=2', json=[]) - self.m_request.get('/api/v1/cluster/2', json={'id': 2}) - - matcher_post = self.m_request.post( - '/api/v1/sequences/1/execute/', json={'id': 10, 'cluster': 2} - ) - self.client.execute(1, 2, dry_run=True, noop_run=False) - self.assertTrue(matcher_post.called) - self.assertIn('"cluster": 2', matcher_post.last_request.body) - self.assertIn('"noop_run": false', matcher_post.last_request.body) - self.assertIn('"dry_run": true', matcher_post.last_request.body) - - def test_upload(self): - matcher_post = self.m_request.post( - '/api/v1/sequences/', json=self.sequence_body - ) - sequence = self.client.upload(1, self.sequence_body) - self.assertTrue(matcher_post.called) - self._check_sequence_object(sequence) - - def test_download(self): - matcher_get = self.m_request.get( - '/api/v1/sequences/1/', json=self.sequence_body - ) - sequence = self.client.download(1) - self.assertTrue(matcher_get.called) - self._check_sequence_object(sequence) diff --git a/fuelclient/tests/unit/v2/lib/test_snapshot.py b/fuelclient/tests/unit/v2/lib/test_snapshot.py deleted file mode 100644 index fae69bfa..00000000 --- a/fuelclient/tests/unit/v2/lib/test_snapshot.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestSnapshotFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestSnapshotFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/logs/package'.format( - version=self.version) - self.client = fuelclient.get_client('snapshot', self.version) - self.fake_task = utils.get_fake_task() - - def test_snapshot_config_download(self): - fake_resp = {'test_key': 'test_value'} - expected_uri = '/api/{version}/logs/package/config/default/'.format( - version=self.version) - - matcher = self.m_request.get(expected_uri, json=fake_resp) - - conf = self.client.get_default_config() - self.assertTrue(matcher.called) - self.assertEqual(conf, fake_resp) - - def test_snapshot_create(self): - fake_config = {} - matcher = self.m_request.put(self.res_uri, json=self.fake_task) - - self.client.create_snapshot(fake_config) - - self.assertTrue(matcher.called) - self.assertEqual(fake_config, matcher.last_request.json()) - - def test_snapshot_create_w_config(self): - fake_config = {'key_value': 'data_value'} - - matcher = self.m_request.put(self.res_uri, json=self.fake_task) - - self.client.create_snapshot(fake_config) - - self.assertTrue(matcher.called) - self.assertEqual(fake_config, matcher.last_request.json()) diff --git a/fuelclient/tests/unit/v2/lib/test_tag.py b/fuelclient/tests/unit/v2/lib/test_tag.py deleted file mode 100644 index c49d4450..00000000 --- a/fuelclient/tests/unit/v2/lib/test_tag.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestTagFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestTagFacade, self).setUp() - - self.version = 'v1' - self.tag_name = 'fake_tag' - self.fake_tag = utils.get_fake_tag(self.tag_name) - self.fake_tags = utils.get_fake_tags(10) - - self.client = fuelclient.get_client('tag', self.version) - - def get_uri(self, owner): - return '/api/{version}/{owner}/'.format(version=self.version, - owner=owner) - - def test_release_tag_list(self): - owner, owner_id = 'releases', 42 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/') - matcher = self.m_request.get(expected_uri, json=self.fake_tags) - self.client.get_all(owner, owner_id) - - self.assertTrue(matcher.called) - - def test_cluster_tag_list(self): - owner, owner_id = 'clusters', 42 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/') - matcher = self.m_request.get(expected_uri, json=self.fake_tags) - self.client.get_all(owner_type=owner, owner_id=owner_id) - - self.assertTrue(matcher.called) - - def test_release_tag_download(self): - owner, owner_id = 'releases', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/{}/'.format(self.tag_name)) - tag_matcher = self.m_request.get(expected_uri, json=self.fake_tag) - - tag = self.client.get_tag(owner, owner_id, self.tag_name) - - self.assertTrue(expected_uri, tag_matcher.called) - self.assertEqual(tag, self.fake_tag) - - def test_cluster_tag_download(self): - owner, owner_id = 'clusters', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/{}/'.format(self.tag_name)) - tag_matcher = self.m_request.get(expected_uri, json=self.fake_tag) - - tag = self.client.get_tag(owner, owner_id, self.tag_name) - - self.assertTrue(expected_uri, tag_matcher.called) - self.assertEqual(tag, self.fake_tag) - - def test_release_tag_update(self): - owner, owner_id = 'releases', 45 - params = {"owner_type": owner, - "owner_id": owner_id, - "tag_name": self.tag_name} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/{}/'.format(self.tag_name)) - upd_matcher = self.m_request.put(expected_uri, json=self.fake_tag) - - self.client.update(self.fake_tag, **params) - - self.assertTrue(upd_matcher.called) - self.assertEqual(self.fake_tag, upd_matcher.last_request.json()) - - def test_cluster_tag_update(self): - owner, owner_id = 'clusters', 45 - params = {"owner_type": owner, - "owner_id": owner_id, - "tag_name": self.tag_name} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/{}/'.format(self.tag_name)) - upd_matcher = self.m_request.put(expected_uri, json=self.fake_tag) - - self.client.update(self.fake_tag, **params) - - self.assertTrue(upd_matcher.called) - self.assertEqual(self.fake_tag, upd_matcher.last_request.json()) - - def test_release_tag_create(self): - owner, owner_id = 'releases', 45 - params = {"owner_type": owner, - "owner_id": owner_id} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/') - post_matcher = self.m_request.post(expected_uri, json=self.fake_tag) - - self.client.create(self.fake_tag, **params) - - self.assertTrue(post_matcher.called) - self.assertEqual(self.fake_tag, post_matcher.last_request.json()) - - def test_cluster_tag_create(self): - owner, owner_id = 'clusters', 45 - params = {"owner_type": owner, - "owner_id": owner_id} - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/') - post_matcher = self.m_request.post(expected_uri, json=self.fake_tag) - - self.client.create(self.fake_tag, **params) - - self.assertTrue(post_matcher.called) - self.assertEqual(self.fake_tag, post_matcher.last_request.json()) - - def test_release_tag_delete(self): - owner, owner_id = 'releases', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/{}/'.format(self.tag_name)) - delete_matcher = self.m_request.delete(expected_uri, json={}) - - self.client.delete(owner, owner_id, self.tag_name) - - self.assertTrue(delete_matcher.called) - - def test_cluster_tag_delete(self): - owner, owner_id = 'clusters', 45 - expected_uri = self.get_object_uri(self.get_uri(owner), - owner_id, - '/tags/{}/'.format(self.tag_name)) - delete_matcher = self.m_request.delete(expected_uri, json={}) - - self.client.delete(owner, owner_id, self.tag_name) - - self.assertTrue(delete_matcher.called) diff --git a/fuelclient/tests/unit/v2/lib/test_task.py b/fuelclient/tests/unit/v2/lib/test_task.py deleted file mode 100644 index fa8a1610..00000000 --- a/fuelclient/tests/unit/v2/lib/test_task.py +++ /dev/null @@ -1,101 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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 fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestTaskFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestTaskFacade, self).setUp() - - self.version = 'v1' - self.res_uri = '/api/{version}/transactions/'\ - .format(version=self.version) - - self.fake_task = utils.get_fake_task() - self.fake_tasks = [utils.get_fake_task() for _ in range(10)] - - self.client = fuelclient.get_client('task', self.version) - - def test_task_list(self): - - matcher = self.m_request.get(self.res_uri, json=self.fake_tasks) - - self.client.get_all() - - self.assertTrue(self.res_uri, matcher.called) - - def test_task_list_w_parameters(self): - env_id = 36 - statuses = ['ready', 'error'] - names = ['dump', 'provision'] - fake_tasks = [ - utils.get_fake_task(task_id=45, cluster=env_id, - status=statuses[0], name=names[0]), - utils.get_fake_task(task_id=46, cluster=env_id, - status=statuses[0], name=names[1]), - utils.get_fake_task(task_id=49, cluster=env_id, - status=[1], name=names[1]), - ] - params = ('?cluster_id={env_id}' - '&statuses={statuses}' - '&transaction_types={names}') - expected_url = self.res_uri + params.format( - env_id=env_id, - statuses=','.join(statuses), - names=','.join(names)) - - matcher = self.m_request.get(expected_url, json=fake_tasks) - - tasks = self.client.get_all(cluster_id=env_id, - statuses=statuses, - transaction_types=names) - - self.assertTrue(matcher.called) - self.assertEqual(3, len(tasks)) - - def test_task_show(self): - task_id = 42 - expected_uri = self.get_object_uri(self.res_uri, task_id) - - matcher = self.m_request.get(expected_uri, json=self.fake_task) - - self.client.get_by_id(task_id) - - self.assertTrue(matcher.called) - - def test_task_delete(self): - task_id = 42 - expected_uri = self.get_object_uri(self.res_uri, task_id) - matcher = self.m_request.delete(expected_uri, json=self.fake_task) - - self.client.delete_by_id(task_id, force=False) - - self.assertTrue(matcher.called) - self.assertEqual(['0'], matcher.last_request.qs.get('force')) - - def test_task_delete_force(self): - task_id = 42 - expected_uri = self.get_object_uri(self.res_uri, task_id) - matcher = self.m_request.delete(expected_uri, json=self.fake_task) - - self.client.delete_by_id(task_id, force=True) - - self.assertTrue(matcher.called) - self.assertEqual(['1'], matcher.last_request.qs.get('force')) diff --git a/fuelclient/tests/unit/v2/lib/test_task_additional_info.py b/fuelclient/tests/unit/v2/lib/test_task_additional_info.py deleted file mode 100644 index 758e4a82..00000000 --- a/fuelclient/tests/unit/v2/lib/test_task_additional_info.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 yaml - -import fuelclient -from fuelclient.tests.unit.v2.lib import test_api -from fuelclient.tests import utils - - -class TestTaskAdditionalInfoFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestTaskAdditionalInfoFacade, self).setUp() - - self.version = 'v1' - self.task_id = 42 - self.res_uri = ( - '/api/{version}/transactions/{task_id}/'.format( - version=self.version, task_id=self.task_id)) - - def _test_info_download(self, client_name, yaml_data, uri): - client = fuelclient.get_client(client_name, self.version) - expected_body = yaml.load(yaml_data) - matcher = self.m_request.get("{0}{1}".format(self.res_uri, uri), - json=expected_body) - result = client.download(self.task_id) - - self.assertTrue(matcher.called) - self.assertEqual(expected_body, result) - - def test_network_configuration_download(self): - self._test_info_download('network-configuration', - utils.get_fake_yaml_network_conf(), - 'network_configuration') - - def test_cluster_settings_download(self): - self._test_info_download('cluster-settings', - utils.get_fake_yaml_cluster_settings(), - 'settings') - - def test_deployment_info_download(self): - self._test_info_download('deployment-info', - utils.get_fake_yaml_deployment_info(), - 'deployment_info') diff --git a/fuelclient/tests/unit/v2/lib/test_vip.py b/fuelclient/tests/unit/v2/lib/test_vip.py deleted file mode 100644 index 9bfb4f84..00000000 --- a/fuelclient/tests/unit/v2/lib/test_vip.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 mock -import yaml - -import fuelclient -from fuelclient.tests.unit.v1.test_vip_action import MANY_VIPS_YAML -from fuelclient.tests.unit.v2.lib import test_api - - -class TestVipFacade(test_api.BaseLibTest): - - def setUp(self): - super(TestVipFacade, self).setUp() - - self.version = 'v1' - self.env_id = 42 - self.res_uri = ( - '/api/{version}/clusters/{env_id}' - '/network_configuration/ips/vips/'.format( - version=self.version, env_id=self.env_id)) - - self.client = fuelclient.get_client('vip', self.version) - - def test_vip_upload(self): - expected_body = yaml.load(MANY_VIPS_YAML) - matcher = self.m_request.put(self.res_uri, json=expected_body) - - m_open = mock.mock_open(read_data=MANY_VIPS_YAML) - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - with mock.patch('fuelclient.objects.environment.os') as env_os: - env_os.path.exists.return_value = True - self.client.upload(self.env_id, 'vips_1.yaml') - - self.assertTrue(matcher.called) - self.assertEqual(expected_body, matcher.last_request.json()) - - def test_vip_download(self): - expected_body = yaml.load(MANY_VIPS_YAML) - matcher = self.m_request.get(self.res_uri, json=expected_body) - - m_open = mock.mock_open() - with mock.patch('fuelclient.cli.serializers.open', - m_open, create=True): - self.client.download(self.env_id) - - self.assertTrue(matcher.called) - - written_yaml = yaml.safe_load(m_open().write.mock_calls[0][1][0]) - expected_yaml = yaml.safe_load(MANY_VIPS_YAML) - self.assertEqual(written_yaml, expected_yaml) - - def test_vip_create(self): - vip_kwargs = {'ip_addr': '127.0.0.1', 'vip_name': 'test', 'network': 1, - 'vip_namespace': 'test-namespace'} - request_post = self.m_request.post(self.res_uri, json={}) - self.client.create(self.env_id, **vip_kwargs) - self.assertTrue(request_post.called) - self.assertEqual(request_post.last_request.json(), vip_kwargs) diff --git a/fuelclient/tests/utils/__init__.py b/fuelclient/tests/utils/__init__.py deleted file mode 100644 index 94bb1d9a..00000000 --- a/fuelclient/tests/utils/__init__.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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. - -from fuelclient.tests.utils.random_data import random_string -from fuelclient.tests.utils.fake_additional_info \ - import get_fake_yaml_cluster_settings -from fuelclient.tests.utils.fake_additional_info \ - import get_fake_yaml_deployment_info -from fuelclient.tests.utils.fake_additional_info \ - import get_fake_yaml_network_conf -from fuelclient.tests.utils.fake_additional_info \ - import get_fake_env_network_conf -from fuelclient.tests.utils.fake_deployment_history \ - import get_fake_deployment_history -from fuelclient.tests.utils.fake_deployment_history \ - import get_fake_deployment_history_w_params -from fuelclient.tests.utils.fake_net_conf import get_fake_interface_config -from fuelclient.tests.utils.fake_net_conf import get_fake_network_config -from fuelclient.tests.utils.fake_network_group import get_fake_network_group -from fuelclient.tests.utils.fake_node import get_fake_node -from fuelclient.tests.utils.fake_env import get_fake_env -from fuelclient.tests.utils.fake_extension import get_fake_env_extensions -from fuelclient.tests.utils.fake_extension import get_fake_extension -from fuelclient.tests.utils.fake_extension import get_fake_extensions -from fuelclient.tests.utils.fake_fuel_version import get_fake_fuel_version -from fuelclient.tests.utils.fake_health import get_fake_test_set -from fuelclient.tests.utils.fake_health import get_fake_test_sets -from fuelclient.tests.utils.fake_health import get_fake_test_set_item -from fuelclient.tests.utils.fake_health import get_fake_test_set_items -from fuelclient.tests.utils.fake_task import get_fake_task -from fuelclient.tests.utils.fake_node_group import get_fake_node_group -from fuelclient.tests.utils.fake_node_group import get_fake_node_groups -from fuelclient.tests.utils.fake_openstack_config \ - import get_fake_openstack_config -from fuelclient.tests.utils.fake_plugin import get_fake_plugin -from fuelclient.tests.utils.fake_plugin import get_fake_plugins -from fuelclient.tests.utils.fake_release import get_fake_release -from fuelclient.tests.utils.fake_release import get_fake_releases -from fuelclient.tests.utils.fake_release import get_fake_attributes_metadata -from fuelclient.tests.utils.fake_release import get_fake_release_component -from fuelclient.tests.utils.fake_release import get_fake_release_components -from fuelclient.tests.utils.fake_role import get_fake_role -from fuelclient.tests.utils.fake_role import get_fake_roles -from fuelclient.tests.utils.fake_tag import get_fake_tag -from fuelclient.tests.utils.fake_tag import get_fake_tags - - -__all__ = (get_fake_deployment_history, - get_fake_deployment_history_w_params, - get_fake_yaml_cluster_settings, - get_fake_yaml_deployment_info, - get_fake_yaml_network_conf, - get_fake_env, - get_fake_env_network_conf, - get_fake_test_set, - get_fake_test_sets, - get_fake_test_set_item, - get_fake_test_set_items, - get_fake_release, - get_fake_releases, - get_fake_attributes_metadata, - get_fake_release_component, - get_fake_release_components, - get_fake_role, - get_fake_roles, - get_fake_fuel_version, - get_fake_interface_config, - get_fake_network_group, - get_fake_node, - get_fake_network_config, - get_fake_task, - random_string, - get_fake_node_group, - get_fake_node_groups, - get_fake_openstack_config, - get_fake_plugin, - get_fake_plugins, - get_fake_tag, - get_fake_tags) diff --git a/fuelclient/tests/utils/fake_additional_info.py b/fuelclient/tests/utils/fake_additional_info.py deleted file mode 100644 index 181918d5..00000000 --- a/fuelclient/tests/utils/fake_additional_info.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 yaml - - -CLUSTER_SETTINGS = '''--- - editable: - service_user: - name: - type: "hidden" - value: "fuel" - sudo: - type: "hidden" - value: "ALL=(ALL) NOPASSWD: ALL" - homedir: - type: "hidden" - value: "/var/lib/fuel" -''' - -DEPLOYMENT_INFO = '''--- -glance_glare: - user_password: yBw0bY60owLC1C0AplHpEiEX -user_node_name: Untitled (5e:89) -uid: '5' -aodh: - db_password: JnEjYacrjxU2TLdTUQE9LdKq - user_password: 8MhyQgtWjWkl0Dv1r1worTjK -mysql: - root_password: bQhzpWjWIOTHOwEA4qNI8X4K - wsrep_password: 01QSoq3bYHgA7oS0OPYQurgX -murano-cfapi: - db_password: hGrAhxUjv3kAPEjiV7uYNwgZ - user_password: 43x0pvQMXugwd8JBaRSQXX4l - enabled: false - rabbit_password: ZqTnnw7lsGQNOFJRN6pTaI8t -''' - -NETWORK_CONF = '''--- - vips: - vrouter_pub: - network_role: "public/vip" - ipaddr: "10.109.3.2" - namespace: "vrouter" - is_user_defined: false - vendor_specific: - iptables_rules: - ns_start: - - "iptables -t nat -A POSTROUTING -o <%INT%> -j MASQUERADE" -''' - - -def get_fake_yaml_cluster_settings(): - """Create a fake cluster settings - - Returns the serialized and parametrized representation of a dumped Fuel - Cluster Settings. Represents the average amount of data. - - """ - return CLUSTER_SETTINGS - - -def get_fake_yaml_deployment_info(): - """Create a fake cluster settings - - Returns the serialized and parametrized representation of a dumped Fuel - Deployment Info. Represents the average amount of data. - - """ - return DEPLOYMENT_INFO - - -def get_fake_yaml_network_conf(): - """Create a fake cluster settings - - Returns the serialized and parametrized representation of a dumped Fuel - Network Conf. Represents the average amount of data. - - """ - return NETWORK_CONF - - -def get_fake_env_network_conf(): - return yaml.load(get_fake_yaml_network_conf()) diff --git a/fuelclient/tests/utils/fake_deployment_history.py b/fuelclient/tests/utils/fake_deployment_history.py deleted file mode 100644 index a8d538dc..00000000 --- a/fuelclient/tests/utils/fake_deployment_history.py +++ /dev/null @@ -1,156 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 itertools - - -def get_fake_deployment_history( - add_task_data=False, convert_legacy_fields=False, - include_summary=False): - """Create a fake deployment history. - - Returns the serialized and parametrized representation of a dumped Fuel - Deployment History. Represents the average amount of data. - - :param add_task_data: add task description to history records using - Fuel 10.0 history output format - :type add_task_data: bool - :param convert_legacy_fields: Fuel 9.0 output fields are renamed to 10.0 - if True - :type convert_legacy_fields: True - :returns: fake deployment fixtures - :rtype: list[dict] - """ - if add_task_data: - result = list(itertools.chain(*[[ - { - 'status': 'ready', - 'time_start': '2016-03-25T17:22:10.687135', - 'time_end': '2016-03-25T17:22:30.830701', - 'node_id': node_id, - 'task_name': 'controller-remaining-tasks', - 'type': 'puppet', - 'role': ['controller'], - 'version': '2.0.0', - 'parameters': { - 'puppet_manifest': '/etc/puppet/modules/osnailyfacter' - '/modular/globals/globals.pp', - 'puppet_modules': '/etc/puppet/modules', - 'timeout': 3600 - }, - }, - { - 'status': 'skipped', - 'time_start': '2016-03-25T17:23:37.313212', - 'time_end': '2016-03-25T17:23:37.313234', - 'node_id': node_id, - 'task_name': 'ironic-compute', - 'type': 'puppet', - 'role': ['controller'], - 'version': '2.0.0', - 'parameters': { - 'puppet_manifest': '/etc/puppet/modules/osnailyfacter' - '/modular/globals/globals.pp', - 'puppet_modules': '/etc/puppet/modules', - 'timeout': 3600 - } - }, - { - 'status': 'pending', - 'time_start': None, - 'node_id': node_id, - 'task_name': 'pending-task', - 'type': 'puppet', - 'role': ['controller'], - 'version': '2.0.0', - 'parameters': { - 'puppet_manifest': '/etc/puppet/modules/osnailyfacter' - '/modular/globals/globals.pp', - 'puppet_modules': '/etc/puppet/modules', - 'timeout': 3600 - } - } - ] for node_id in ['1', '2']])) - else: - result = list(itertools.chain(*[[ - { - 'status': 'ready', - 'time_start': '2016-03-25T17:22:10.687135', - 'time_end': '2016-03-25T17:22:30.830701', - 'node_id': node_id, - 'deployment_graph_task_name': 'controller-remaining-tasks', - }, - { - 'status': 'skipped', - 'time_start': '2016-03-25T17:23:37.313212', - 'time_end': '2016-03-25T17:23:37.313234', - 'node_id': node_id, - 'deployment_graph_task_name': 'ironic-compute' - }, - { - 'status': 'pending', - 'time_start': None, - 'node_id': node_id, - 'deployment_graph_task_name': 'pending-task' - } - ] for node_id in ['1', '2']])) - - if convert_legacy_fields: - for record in result: - record['task_name'] = record['deployment_graph_task_name'] - record.pop('deployment_graph_task_name', None) - if include_summary: - for record in result: - record['summary'] = '{}' - return result - - -def get_fake_deployment_history_w_params(): - return [ - { - 'task_name': 'controller-remaining-tasks', - 'task_parameters': 'parameters: {puppet_manifest: /etc/puppet/' - 'modules/osnailyfacter/modular/globals/' - 'globals.pp,\n puppet_modules: /etc/' - 'puppet/modules, timeout: 3600}\nrole: ' - '[controller]\ntype: puppet\nversion: 2.0.0' - '\n', - 'status_by_node': '1 - ready - 2016-03-25T17:22:10 - ' - '2016-03-25T17:22:30\n' - '2 - ready - 2016-03-25T17:22:10 - ' - '2016-03-25T17:22:30' - }, - { - 'task_name': 'pending-task', - 'task_parameters': 'parameters: {puppet_manifest: /etc/puppet/' - 'modules/osnailyfacter/modular/globals/' - 'globals.pp,\n puppet_modules: /etc/puppet' - '/modules, timeout: 3600}\nrole: ' - '[controller]\ntype: puppet\nversion: 2.0.0' - '\n', - 'status_by_node': '1 - pending - not started - not ended\n' - '2 - pending - not started - not ended' - }, - { - 'task_name': 'ironic-compute', - 'status_by_node': '1 - skipped - 2016-03-25T17:23:37 - ' - '2016-03-25T17:23:37\n2 - skipped - ' - '2016-03-25T17:23:37 - 2016-03-25T17:23:37', - 'task_parameters': 'parameters: {puppet_manifest: /etc/puppet/' - 'modules/osnailyfacter/modular/globals/' - 'globals.pp,\n puppet_modules: /etc/' - 'puppet/modules, timeout: 3600}\nrole: ' - '[controller]\ntype: puppet\nversion: 2.0.0\n'}, - ] diff --git a/fuelclient/tests/utils/fake_env.py b/fuelclient/tests/utils/fake_env.py deleted file mode 100644 index 200856a9..00000000 --- a/fuelclient/tests/utils/fake_env.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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. - - -def get_fake_env(name=None, status=None, release_id=None, - fuel_version=None, env_id=None): - """Create a random fake environment - - Returns the serialized and parametrized representation of a dumped Fuel - environment. Represents the average amount of data. - - """ - return {'status': status or 'new', - 'is_customized': False, - 'release_id': release_id or 2, - 'name': name or 'fake_env', - 'fuel_version': fuel_version or '10.0', - 'id': env_id or 1, - 'changes': []} diff --git a/fuelclient/tests/utils/fake_extension.py b/fuelclient/tests/utils/fake_extension.py deleted file mode 100644 index eaa57f08..00000000 --- a/fuelclient/tests/utils/fake_extension.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - - -def get_fake_env_extensions(names=None): - """Create a list of fake extensions for particular env""" - - return names or ['fake_ext1', 'fake_ext2', 'fake_ext3'] - - -def get_fake_extension(name=None, version=None, provides=None, - description=None): - return {'name': name or 'fake_name', - 'version': version or 'fake_version', - 'provides': provides or ['fake_method_call'], - 'description': description or 'fake_description', - } - - -def get_fake_extensions(extension_count, **kwargs): - """Create a random fake list of extensions.""" - return [get_fake_extension(**kwargs) - for _ in range(extension_count)] diff --git a/fuelclient/tests/utils/fake_fuel_version.py b/fuelclient/tests/utils/fake_fuel_version.py deleted file mode 100644 index 97b84977..00000000 --- a/fuelclient/tests/utils/fake_fuel_version.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - - -def get_fake_fuel_version(): - """Creates a fake fuel version - - Returns the serialized and parametrized representation of a dumped Fuel - environment. Represents the average amount of data. - - """ - return {"api": "1", - "auth_required": True, - "feature_groups": ['advanced'], - "openstack_version": "newton-10.0", - "release": "10.0"} diff --git a/fuelclient/tests/utils/fake_health.py b/fuelclient/tests/utils/fake_health.py deleted file mode 100644 index 711ee24e..00000000 --- a/fuelclient/tests/utils/fake_health.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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. - - -def get_fake_test_set(testset_id=None, name=None): - """Create a random fake test set for environment.""" - return { - "id": testset_id or "fake_test_set", - "name": name or "Fake tests. Duration 30 sec - 2 min" - } - - -def get_fake_test_sets(testsets_count, **kwargs): - """Create a random fake list of test sets for environment.""" - return [get_fake_test_set(**kwargs) - for _ in range(testsets_count)] - - -def get_fake_test_set_item(testset_id=None, testset=None, cluster_id=None, - status=None, tests=None): - """Create a random fake test set item.""" - return { - "id": testset_id or 45, - "testset": testset or "fake_test_set", - "cluster_id": cluster_id or 65, - "status": status or "finished", - "started_at": "2016-09-15 09:03:07.697393", - "ended_at": "2016-09-15 09:03:19.280296", - "tests": tests or [ - { - "status": "failure", - "taken": 1.0, - "testset": "fake_test_set", - "name": "Create fake instance", - "duration": "30 s.", - "message": "Fake test message", - "id": "fuel_health.tests.fake_test", - "description": "fake description" - }, - { - "status": "stopped", - "taken": 0.5, - "testset": "fake_test_set", - "name": "Check create, update and delete fake instance image", - "duration": "70 s.", - "message": "Can not set proxy for Health Check.", - "id": "fuel_health.tests.fake_test.test_update_fake_images", - "description": "fake description" - } - ] - } - - -def get_fake_test_set_items(items_count, **kwargs): - """Create a random fake list of test sets items.""" - return [get_fake_test_set_item(**kwargs) - for _ in range(items_count)] diff --git a/fuelclient/tests/utils/fake_net_conf.py b/fuelclient/tests/utils/fake_net_conf.py deleted file mode 100644 index 1cb6c852..00000000 --- a/fuelclient/tests/utils/fake_net_conf.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 random - -from six import moves as six_moves - - -def get_fake_interface_config(iface=None, iface_id=None, state=None, mac=None, - iface_type=None, networks=None): - """Create a random fake interface configuration - - Returns the serialized and parametrized representation of a node's - interface configuration. Represents the average amount of data. - - """ - - return {"name": iface or "eth0", - "id": iface_id or random.randint(0, 1000), - "state": state or "unknown", - "mac": mac or "08:00:27:a4:01:6b", - "max_speed": 100, - "type": iface_type or "ether", - "current_speed": 100, - "assigned_networks": networks or [{"id": 1, - "name": "fuelweb_admin"}, - {"id": 3, - "name": "management"}, - {"id": 4, - "name": "storage"}, - {"id": 5, - "name": "fixed"}]} - - -def get_fake_network_config(iface_number): - """Creates a fake network configuration for a single node.""" - - return [get_fake_interface_config(iface='eth{0}'.format(i)) - for i in six_moves.range(iface_number)] diff --git a/fuelclient/tests/utils/fake_network_group.py b/fuelclient/tests/utils/fake_network_group.py deleted file mode 100644 index 2d2dab36..00000000 --- a/fuelclient/tests/utils/fake_network_group.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - - -def get_fake_network_group( - name=None, release=None, vlan=None, cidr=None, gateway=None, - group_id=None, meta=None, net_id=None): - """Create a random fake network group - - Returns the serialized and parametrized representation of a dumped Fuel - environment. Represents the average amount of data. - - """ - return { - 'name': name or 'testng', - 'release': release or 24, - 'vlan_start': vlan or 10, - 'cidr': cidr or '10.0.0.0/24', - 'gateway': gateway or '10.0.0.1', - 'group_id': group_id or 42, - 'meta': meta or {'notation': 'cidr'}, - 'id': net_id or 42, - } diff --git a/fuelclient/tests/utils/fake_node.py b/fuelclient/tests/utils/fake_node.py deleted file mode 100644 index ced8c8da..00000000 --- a/fuelclient/tests/utils/fake_node.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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. - - -def get_fake_node(cluster=None, hostname=None, node_id=None, cpu_model=None, - roles=None, mac=None, memory_b=None, os_platform=None, - status=None, node_name=None, group_id=None, labels=None, - ip=None): - """Creates a fake node - - Returns the serialized and parametrized representation of a dumped Fuel - environment. Represents the average amount of data. - - """ - host_name = hostname or 'fake-node-42' - labels = labels or { - 'key_1': 'val_1', - 'key_2': None, - 'key_3': 'val_3' - } - - return {'name': node_name or host_name, - 'error_type': None, - 'cluster': cluster or 1, - 'id': node_id or 42, - 'ip': ip or '10.20.0.4', - 'kernel_params': None, - 'group_id': group_id or 1, - 'mac': mac or 'd6:11:3f:b0:f1:43', - 'manufacturer': 'VirtualBox', - 'online': True, - 'os_platform': os_platform or 'ubuntu', - 'pending_addition': False, - 'pending_deletion': False, - 'pending_roles': [], - 'platform_name': None, - 'progress': 100, - 'roles': roles or ['compute'], - 'status': status or 'ready', - 'hostname': host_name, - 'fqdn': '{hostname}.example.com'.format(hostname=host_name), - - 'meta': {'cpu': {'real': 0, - 'spec': [{'frequency': 2553, - 'model': cpu_model or 'Random CPU'}], - 'total': 1}, - - 'disks': [{'disk': 'disk/by-path/pci:00:0d.0-scsi-2:0:0', - 'extra': ['disk/by-id/scsi-SATA_VBOX_aef0bb5c', - 'disk/by-id/ata-VBOX_HARDDISK_VB37'], - 'model': 'VBOX HARDDISK', - 'name': 'sdc', - 'removable': '0', - 'size': 68718428160}, - - {'disk': 'disk/by-path/pci:0:0d.0-scsi-1:0:0:0', - 'extra': ['disk/by-id/scsi-SATA_VBOX_30fbc3bb', - 'disk/by-id/ata-VBOX_HARDD30fbc3bb'], - 'model': 'VBOX HARDDISK', - 'name': 'sdb', - 'removable': '0', - 'size': 68718428160}, - - {'disk': 'disk/by-path/pci:00:d.0-scsi-0:0:0:0', - 'extra': ['disk/by-id/scsi-SATA_VBOX-17e33653', - 'disk/by-id/ata-VBOX_HARDD17e33653'], - 'model': 'VBOX HARDDISK', - 'name': 'sda', - 'removable': '0', - 'size': 68718428160}], - - 'interfaces': [{'name': 'eth2', - 'current_speed': 100, - 'mac': '08:00:27:88:9C:46', - 'max_speed': 100, - 'state': 'unknown'}, - - {'name': 'eth1', - 'current_speed': 100, - 'mac': '08:00:27:24:BD:6D', - 'max_speed': 100, - 'state': 'unknown'}, - - {'name': 'eth0', - 'current_speed': 100, - 'mac': '08:00:27:C1:C5:72', - 'max_speed': 100, - 'state': 'unknown'}], - 'memory': {'total': memory_b or 1968627712}, - - 'system': {'family': 'Virtual Machine', - 'fqdn': host_name, - 'manufacturer': 'VirtualBox', - 'serial': '0', - 'version': '1.2'}}, - 'network_data': [{'brd': '192.168.0.255', - 'dev': 'eth0', - 'gateway': None, - 'ip': '192.168.0.2/24', - 'name': 'management', - 'netmask': '255.255.255.0', - 'vlan': 101}, - - {'brd': '192.168.1.255', - 'dev': 'eth0', - 'gateway': None, - 'ip': '192.168.1.2/24', - 'name': 'storage', - 'netmask': '255.255.255.0', - 'vlan': 102}, - - {'brd': '172.16.0.255', - 'dev': 'eth1', - 'gateway': '172.16.0.1', - 'ip': '172.16.0.3/24', - 'name': 'public', - 'netmask': '255.255.255.0', - 'vlan': None}, - - {'dev': 'eth0', - 'name': 'admin'}], - 'labels': labels} diff --git a/fuelclient/tests/utils/fake_node_group.py b/fuelclient/tests/utils/fake_node_group.py deleted file mode 100644 index 0f4a1be7..00000000 --- a/fuelclient/tests/utils/fake_node_group.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - - -def get_fake_node_group(name=None, cluster_id=None, id=None): - """Create a random fake network node group - - Returns the serialized and parametrized representation of a dumped Fuel - nodegroup. Represents the average amount of data. - - """ - return { - 'name': name or 'testng', - 'id': id or 42, - 'cluster_id': cluster_id or 5, - } - - -def get_fake_node_groups(): - """Create a fake network node group list - - Returns the serialized and parametrized representation of a dumped Fuel - nodegroups list. - - """ - return [ - {"cluster_id": 1, "id": 1, "name": "default"}, - {"cluster_id": 1, "id": 2, "name": "custom-group"} - ] diff --git a/fuelclient/tests/utils/fake_openstack_config.py b/fuelclient/tests/utils/fake_openstack_config.py deleted file mode 100644 index 06360b55..00000000 --- a/fuelclient/tests/utils/fake_openstack_config.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2015 Mirantis, 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. - - -def get_fake_openstack_config( - id=None, config_type=None, cluster_id=None, node_id=None, - node_role=None, configuration=None): - config = { - 'id': id or 42, - 'is_active': True, - 'config_type': config_type or 'cluster', - 'cluster_id': cluster_id or 84, - 'node_id': node_id or None, - 'node_role': node_role or None, - 'configuration': configuration or { - 'nova_config': { - 'DEFAULT/debug': { - 'value': True, - }, - }, - 'keystone_config': { - 'DEFAULT/debug': { - 'value': True, - }, - }, - }, - } - return config diff --git a/fuelclient/tests/utils/fake_plugin.py b/fuelclient/tests/utils/fake_plugin.py deleted file mode 100644 index 0db9f540..00000000 --- a/fuelclient/tests/utils/fake_plugin.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding:utf8 -*- -# -# Copyright 2016 Mirantis, 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 six -from six import moves as six_moves - - -def get_fake_plugin(**kwargs): - """Creates a fake plugin - - Returns the serialized and parametrized representation of a dumped Fuel - Plugin. Represents the average amount of data. - - """ - plugin = {'id': 1, - 'name': 'plugin_name', - 'title': 'plugin_title', - 'version': '1.0.0', - 'description': 'plugin_description', - 'authors': ['author1', 'author2'], - 'package_version': '3.0.0', - 'releases': [{'os': 'ubuntu', - 'version': 'liberty-8.0'}, - {'os': 'ubuntu', - 'version': 'mitaka-9.0'}], - 'is_hotpluggable': True} - for k, v in six.iteritems(kwargs): - if k in plugin: - plugin[k] = v - return plugin - - -def get_fake_plugins(plugins_number, **kwargs): - """Creates fake plugins list.""" - return [get_fake_plugin(plugin_id=i, **kwargs) - for i in six_moves.range(1, plugins_number + 1)] diff --git a/fuelclient/tests/utils/fake_release.py b/fuelclient/tests/utils/fake_release.py deleted file mode 100644 index 9a74649d..00000000 --- a/fuelclient/tests/utils/fake_release.py +++ /dev/null @@ -1,129 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - - -def get_fake_attributes_metadata(repos=None): - return { - 'editable': { - 'repo_setup': { - 'repos': { - 'value': repos or [ - { - 'name': 'upstream', - 'type': 'deb', - 'uri': 'fake_upstream_uri', - 'suite': 'trusty', - 'section': 'main restricted', - 'priority': 1000 - }, - { - 'name': 'mos', - 'type': 'deb', - 'uri': 'fake_mos_uri', - 'suite': 'mos', - 'section': 'main restricted', - 'priority': 1050 - } - ] - } - } - } - } - - -def get_fake_release(release_id=None, name=None, state=None, - operating_system=None, version=None, repos=None): - """Create a random fake release - - Returns the serialized and parametrized representation of a dumped Fuel - release. Represents the average amount of data. - - """ - return { - 'id': release_id or 1, - 'name': name or 'Mitaka on Ubuntu 14.04', - 'state': state or 'available', - 'operating_system': operating_system or 'environment', - 'version': version or 'mitaka-9.0', - 'attributes_metadata': get_fake_attributes_metadata(repos=repos), - } - - -def get_fake_releases(release_count, **kwargs): - """Create a random fake release list.""" - return [get_fake_release(release_id=i, **kwargs) - for i in range(1, release_count + 1)] - - -def get_fake_release_component(name=None, requires=None, incompatible=None, - compatible=None, default=None): - """Create a random fake component of release - - Returns the serialized and parametrized representation of a dumped Fuel - component of release. Represents the average amount of data. - - """ - return { - 'name': name or 'network:neutron:ml2:vlan', - 'description': - 'dialog.create_cluster_wizard.network.neutron_vlan_description', - 'weight': 5, - 'requires': requires or [ - { - 'one_of': { - 'items': ['hypervisor:qemu'], - 'message': 'dialog.create_cluster_wizard.compute.' - 'vcenter_warning' - } - }, - { - 'one_of': { - 'items': ['network:neutron:ml2:dvs', - 'network:neutron:ml2:nsx'], - 'message': 'dialog.create_cluster_wizard.compute.' - 'vcenter_requires_network_backend', - 'message_invalid': 'dialog.create_cluster_wizard.compute.' - 'vcenter_requires_network_plugins' - } - } - ], - 'incompatible': incompatible or [ - {'message': 'dialog.create_cluster_wizard.network.vlan_tun_alert', - 'name': 'network:neutron:ml2:tun'} - ], - 'compatible': compatible or [ - {'name': 'network:neutron:core:ml2'}, - {'name': 'hypervisor:qemu'}, - {'name': 'hypervisor:vmware'}, - {'name': 'storage:block:lvm'}, - {'name': 'storage:block:ceph'}, - {'name': 'storage:object:ceph'}, - {'name': 'storage:ephemeral:ceph'}, - {'name': 'storage:image:ceph'}, - {'name': 'additional_service:sahara'}, - {'name': 'additional_service:murano'}, - {'name': 'additional_service:ceilometer'}, - {'name': 'additional_service:ironic'} - ], - 'default': default, - 'label': 'common.network.neutron_vlan', - } - - -def get_fake_release_components(component_count, **kwargs): - """Create a random fake list of release components.""" - return [get_fake_release_component(**kwargs) - for _ in range(component_count)] diff --git a/fuelclient/tests/utils/fake_role.py b/fuelclient/tests/utils/fake_role.py deleted file mode 100644 index d9d2d5b2..00000000 --- a/fuelclient/tests/utils/fake_role.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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. - - -def get_fake_role(name=None, meta=None, volumes_roles_mapping=None): - """Create a random fake role - - Returns the serialized and parametrized representation of a dumped Fuel - role. Represents the average amount of data. - - """ - return { - "name": name or "controller", - "meta": meta or { - "group": "base", - "name": "Controller", - "conflicts": ["compute", "ceph-osd"], - "description": "The Controller initiates orchestration activities " - "and provides an external API. Other components " - "like Glance (image storage), Keystone (identity " - "management), Horizon (OpenStack dashboard) and " - "Nova-Scheduler are installed on the controller " - "as well." - }, - "volumes_roles_mapping": volumes_roles_mapping or [ - {"id": "os", "allocate_size": "min"}, - {"id": "logs", "allocate_size": "min"}, - {"id": "image", "allocate_size": "all"}, - {"id": "mysql", "allocate_size": "min"}, - {"id": "horizon", "allocate_size": "min"} - ] - } - - -def get_fake_roles(role_count, **kwargs): - """Create a random fake list of roles.""" - return [get_fake_role(**kwargs) - for _ in range(role_count)] diff --git a/fuelclient/tests/utils/fake_tag.py b/fuelclient/tests/utils/fake_tag.py deleted file mode 100644 index d516b890..00000000 --- a/fuelclient/tests/utils/fake_tag.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - - -def get_fake_tag(tag_name=None, has_primary=False, owner_id=None, - owner_type=None): - """Create a random fake tag - - Returns the serialized and parametrized representation of a dumped Fuel - tag. Represents the average amount of data. - - """ - return { - "id": 1, - "tag": tag_name or "controller", - "has_primary": has_primary, - "owner_id": owner_id or 1, - "owner_type": owner_type or 'release' - } - - -def get_fake_tags(tag_count, **kwargs): - """Create a random fake list of tags.""" - return [get_fake_tag(**kwargs) for _ in range(tag_count)] diff --git a/fuelclient/tests/utils/fake_task.py b/fuelclient/tests/utils/fake_task.py deleted file mode 100644 index d1a35762..00000000 --- a/fuelclient/tests/utils/fake_task.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2015 Mirantis, 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. - - -def get_fake_task(task_id=None, status=None, name=None, - cluster=None, result=None, progress=None, - message=None, uuid=None): - """Create a fake task - - Returns the serialized and parametrized representation of a dumped Fuel - Task. Represents the average amount of data. - - """ - return {'status': status or 'running', - 'name': name or 'deploy', - 'id': task_id or 42, - 'uuid': uuid or '14474652-4f3e-4dc6-b2f3-5921b62b4a9e', - 'message': message or 'I am a human being!', - 'task_id': task_id or 42, - 'cluster': cluster or 34, - 'result': result or '', - 'progress': progress or 50} diff --git a/fuelclient/tests/utils/random_data.py b/fuelclient/tests/utils/random_data.py deleted file mode 100644 index 942e9096..00000000 --- a/fuelclient/tests/utils/random_data.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2014 Mirantis, 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 random -import string - - -def random_string(lenght, prefix='', postfix='', charset=None): - """Returns a random string of the specified length - - :param length: The length of the resulting string. - :type lenght: int. - :param prefix: Prefix for the random string. - :type prefix: str, default: ''. - :param postfix: Postfix for the random string. - :type postfix: str, default ''. - :param charset: A set of characters to use for building random strings. - :type chartet: Iterable object. Default: ASCII letters and digits. - :return: str - - """ - charset = charset or string.ascii_letters + string.digits - base_length = lenght - (len(prefix) + len(postfix)) - - base = ''.join([str(random.choice(charset)) for i in range(base_length)]) - - return '{prefix}{base}{postfix}'.format(prefix=prefix, - postfix=postfix, - base=base) diff --git a/fuelclient/utils.py b/fuelclient/utils.py deleted file mode 100644 index 856f7ac9..00000000 --- a/fuelclient/utils.py +++ /dev/null @@ -1,214 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2015 Mirantis, 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 functools -import glob -import io -import os -import six -import subprocess -import sys -import yaml - -from distutils.version import StrictVersion -from fnmatch import fnmatch - -from fuelclient.cli import error - - -def _wait_and_check_exit_code(cmd, child): - """Wait for child and check it's exit code - - :param cmd: command - :param child: object which returned by subprocess.Popen - :raises: ExecutedErrorNonZeroExitCode - """ - child.wait() - exit_code = child.returncode - - if exit_code != 0: - raise error.ExecutedErrorNonZeroExitCode( - u'Shell command executed with "{0}" ' - 'exit code: {1} '.format(exit_code, cmd)) - - -def exec_cmd(cmd, cwd=None): - """Execute shell command logging. - - :param str cmd: shell command - :param str cwd: None is default - """ - child = subprocess.Popen( - cmd, stdout=None, - stderr=subprocess.STDOUT, - shell=True, - cwd=cwd) - - _wait_and_check_exit_code(cmd, child) - - -def exec_cmd_iterator(cmd): - """Execute command with logging. - :param cmd: shell command - :returns: generator where yeach item - is line from stdout - """ - child = subprocess.Popen( - cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True) - - for line in child.stdout: - yield line - - _wait_and_check_exit_code(cmd, child) - - -def parse_yaml_file(path): - """Parses yaml - - :param str path: path to yaml file - :returns: deserialized file - """ - with io.open(path, encoding='utf-8') as f: - data = yaml.load(f) - - return data - - -def glob_and_parse_yaml(path): - """Parses yaml files by mask. - - :param str path: mask - :returns: iterator - """ - for f in glob.iglob(path): - yield parse_yaml_file(f) - - -def major_plugin_version(version): - """Retrieves major version. - "1.2.3" -> "1.2" - - :param str version: version - :returns: only major version - """ - version_tuple = StrictVersion(version).version - major = '.'.join(map(str, version_tuple[:2])) - - return major - - -def iterfiles(dir_path, file_pattern): - """Returns generator where each item is a path to file, that satisfies - file_patterns condtion - - :param dir_path: path to directory, e.g /etc/puppet/ - :param file_pattern: unix filepattern to match files - """ - for root, dirs, file_names in os.walk(dir_path, followlinks=True): - for file_name in file_names: - if fnmatch(file_name, file_pattern): - yield os.path.join(root, file_name) - - -def file_exists(path): - """Checks if file exists - - :param str path: path to the file - :returns: True if file is exist, Flase if is not - """ - return os.path.lexists(path) - - -def parse_to_list_of_dicts(items): - """Parse list of json strings to dictionaries - - :param list: list of dicts and json string - :returns" list of dictionaries - - """ - dict_list = [] - for item in items: - if isinstance(item, dict): - dict_list.append(item) - elif isinstance(item, list): - dict_list.extend(item) - else: - raise TypeError( - 'A dict or list instance expected: {0}'.format(item)) - return dict_list - - -def str_to_unicode(string): - """Normalize input string from command line to unicode standard. - - :param str string: string to normalize - :returns: normalized string - - """ - return string if six.PY3 else string.decode(sys.getfilesystemencoding()) - - -def find_exec(program): - """Tries to find an executable in PATHs. - - :param str program: Name of executable to find - """ - for path in os.getenv('PATH').split(os.pathsep): - path = path.strip('"') - candidate = os.path.join(path, program) - if os.path.isfile(candidate) and os.access(candidate, os.X_OK): - return candidate - - -def safe_deserialize(loader): - """Wrapper for deserializers. - - Exceptions are raising during deserialization will be transformed - into BadDataException - - :param loader: deserializer function - :return: wrapped loader - """ - @functools.wraps(loader) - def wrapper(data): - try: - return loader(data) - except (ValueError, TypeError, yaml.error.YAMLError) as e: - raise error.BadDataException('{0}: {1}' - ''.format(e.__class__.__name__, - six.text_type(e))) - return wrapper - - -def add_os_cli_parameters(parser): - parser.add_argument( - '--os-auth-url', metavar='', - help='Authentication URL, defaults to env[OS_AUTH_URL].') - - parser.add_argument( - '--os-tenant-name', metavar='', - help='Authentication tenant name, defaults to ' - 'env[OS_TENANT_NAME].') - - parser.add_argument( - '--os-username', metavar='', - help='Authentication username, defaults to env[OS_USERNAME].') - - parser.add_argument( - '--os-password', metavar='', - help='Authentication password, defaults to env[OS_PASSWORD].') diff --git a/fuelclient/v1/__init__.py b/fuelclient/v1/__init__.py deleted file mode 100644 index d1039522..00000000 --- a/fuelclient/v1/__init__.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.v1 import cluster_settings -from fuelclient.v1 import deployment_history -from fuelclient.v1 import deployment_info -from fuelclient.v1 import environment -from fuelclient.v1 import extension -from fuelclient.v1 import fuelversion -from fuelclient.v1 import graph -from fuelclient.v1 import health -from fuelclient.v1 import network_configuration -from fuelclient.v1 import network_group -from fuelclient.v1 import node -from fuelclient.v1 import openstack_config -from fuelclient.v1 import release -from fuelclient.v1 import role -from fuelclient.v1 import plugins -from fuelclient.v1 import sequence -from fuelclient.v1 import snapshot -from fuelclient.v1 import task -from fuelclient.v1 import tag -from fuelclient.v1 import vip - -# Please keeps the list in alphabetical order -__all__ = ('cluster_settings', - 'deployment_history', - 'deployment_info', - 'environment', - 'extension', - 'fuelversion', - 'graph', - 'health', - 'network_configuration', - 'network_group', - 'node', - 'openstack_config', - 'plugins', - 'release', - 'role', - 'sequence', - 'snapshot', - 'task', - 'tag', - 'vip') diff --git a/fuelclient/v1/base_v1.py b/fuelclient/v1/base_v1.py deleted file mode 100644 index 3639eba1..00000000 --- a/fuelclient/v1/base_v1.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2015 Mirantis, 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 abc - -import six - -from fuelclient import client - - -@six.add_metaclass(abc.ABCMeta) -class BaseV1Client(object): - - @abc.abstractproperty - def _entity_wrapper(self): - pass - - def __init__(self, connection=None): - if connection is None: - connection = client.DefaultAPIClient - self.connection = connection - - cls_wrapper = self.__class__._entity_wrapper - self._entity_wrapper = type( - cls_wrapper.__name__, - (cls_wrapper, ), - {'connection': self.connection} - ) - - def get_all(self, **kwargs): - filters = {} - for k, v in six.iteritems(kwargs): - if isinstance(v, list): - if v: - filters[k] = ','.join(str(s) for s in v) - elif v is not None: - filters[k] = str(v) - result = self._entity_wrapper.get_all_data(**filters) - - return result - - def get_by_id(self, entity_id): - obj = self._entity_wrapper(obj_id=entity_id) - - return obj.data diff --git a/fuelclient/v1/cluster_settings.py b/fuelclient/v1/cluster_settings.py deleted file mode 100644 index e5140ded..00000000 --- a/fuelclient/v1/cluster_settings.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class ClusterSettingsClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Task - - def download(self, transaction_id): - task = self._entity_wrapper(transaction_id) - return task.cluster_settings() - - -def get_client(connection): - return ClusterSettingsClient(connection) diff --git a/fuelclient/v1/deployment_history.py b/fuelclient/v1/deployment_history.py deleted file mode 100644 index dad4312b..00000000 --- a/fuelclient/v1/deployment_history.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2016 Mirantis, 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. -from collections import defaultdict - -import six -import yaml - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class DeploymentHistoryClient(base_v1.BaseV1Client): - - class_api_path = "transactions/{transaction_id}/deployment_history/" - - history_records_keys = ("task_name", "node_id", "status", - "time_start", "time_end") - tasks_records_keys = ("task_name", "task_parameters", "status_by_node") - - _entity_wrapper = objects.Environment - - def get_all(self, transaction_id, nodes=None, statuses=None, - tasks_names=None, show_parameters=False, - include_summary=False): - parameters = { - 'statuses': statuses, - 'nodes': nodes, - 'tasks_names': tasks_names, - 'include_summary': (str(int(include_summary)),), - } - # remove unused parameters or parameters with empty list as value - parameters = {k: v for k, v in six.iteritems(parameters) - if v is not None and v} - # 'parameters': ['param1', 'param2'] --> 'parameters': 'param1,param2' - for k in parameters: - parameters[k] = ",".join(s for s in parameters[k]) - - history_with_tasks = self.connection.get_request( - self.class_api_path.format( - transaction_id=transaction_id, - ), params=parameters - ) - # rename legacy field for Fuel 9.0 - for record in history_with_tasks: - if 'deployment_graph_task_name' in record: - record['task_name'] = record['deployment_graph_task_name'] - record.pop('deployment_graph_task_name', None) - - # metadata for each task - tasks_parameters = defaultdict(dict) - # history records by task ID - history_records_by_task = defaultdict(list) - # history records in initial order - history_records = [] - # split keys to history- and task-specific - - for record in history_with_tasks: - task_name = record['task_name'] - if tasks_names and task_name not in tasks_names: - # API gave us a task, that we actually want to filter out - continue - history_record = {} - for key in record: - if key in self.history_records_keys or key == 'summary': - history_record[key] = record[key] - else: - tasks_parameters[task_name][key] = record[key] - if include_summary: - history_record['summary'] = history_record.get('summary', None) - history_records.append(history_record) - history_records_by_task[task_name].append(history_record) - - if show_parameters: - result = [] - for task_name, value in sorted(six.iteritems(tasks_parameters)): - statuses_by_node = [] - for record in history_records_by_task[task_name]: - time_start = record.get('time_start') - time_start = time_start.partition(u'.')[0] if time_start\ - else u'not started' - record['time_start'] = time_start - time_end = record.get('time_end') - time_end = time_end.partition(u'.')[0] if time_end \ - else u'not ended' - record['time_end'] = time_end - - statuses_by_node.append( - '{node_id} - {status} - {time_start} - {time_end}' - ''.format(**record) - ) - - result.append( - { - "task_name": task_name, - "task_parameters": yaml.safe_dump( - tasks_parameters[task_name]), - "status_by_node": '\n'.join(statuses_by_node) - } - ) - return result - else: - return history_records - - -def get_client(connection): - return DeploymentHistoryClient(connection) diff --git a/fuelclient/v1/deployment_info.py b/fuelclient/v1/deployment_info.py deleted file mode 100644 index 14555d1f..00000000 --- a/fuelclient/v1/deployment_info.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class DeploymentInfoClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Task - - def download(self, transaction_id): - task = self._entity_wrapper(transaction_id) - return task.deployment_info() - - -def get_client(connection): - return DeploymentInfoClient(connection) diff --git a/fuelclient/v1/environment.py b/fuelclient/v1/environment.py deleted file mode 100644 index 6b7725f5..00000000 --- a/fuelclient/v1/environment.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.cli import error -from fuelclient import objects -from fuelclient.v1 import base_v1 -from fuelclient.v1 import fuelversion - - -class EnvironmentClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Environment - _updatable_attributes = ('name',) - - provision_nodes_url = 'clusters/{env_id}/provision/?nodes={nodes}' - deploy_nodes_url = ('clusters/{env_id}/deploy/?' - 'nodes={nodes}&force={force}&noop_run={noop_run}') - - def create(self, name, release_id, net_segment_type): - - supported_nst = ('gre', 'vlan', 'tun') - - if net_segment_type not in supported_nst: - msg = ('Network segmentation type should be one ' - 'of {0}'.format(' '.join(supported_nst))) - raise error.BadDataException(msg) - - env = self._entity_wrapper.create(name, release_id, net_segment_type) - - return env.data - - def update(self, environment_id, **kwargs): - allowed_changes = {} - extra_args = {} - - for i in kwargs: - if i in self._updatable_attributes: - allowed_changes[i] = kwargs[i] - else: - extra_args[i] = kwargs[i] - - if extra_args != {}: - msg = 'Only {0} are updatable'.format(self._updatable_attributes) - raise error.BadDataException(msg) - - env = self._entity_wrapper(obj_id=environment_id) - env.set(allowed_changes) - - return env.data - - def delete_by_id(self, environment_id): - env_obj = self._entity_wrapper(obj_id=environment_id) - env_obj.delete() - - def add_nodes(self, environment_id, nodes, roles): - env = self._entity_wrapper(obj_id=environment_id) - nodes = [objects.Node(obj_id=n_id) for n_id in nodes] - - env.assign(nodes, roles) - - def remove_nodes(self, environment_id, nodes=None): - """Remove nodes from environment. If nodes are empty list then - all nodes will be removed - - :param environment_id: Id of specific environment (cluster) - :type environment_id: int - :param nodes: List of node ids that should be removed - :type nodes: list - """ - env = self._entity_wrapper(obj_id=environment_id) - if nodes is not None: - env.unassign(nodes) - else: - env.unassign_all() - - def deploy_changes(self, environment_id, dry_run=False, noop_run=False): - env = self._entity_wrapper(obj_id=environment_id) - - deploy_task = env.deploy_changes(dry_run=dry_run, noop_run=noop_run) - return deploy_task.id - - def provision_nodes(self, environment_id, node_ids): - """Provision specified nodes for the specified environment.""" - - nodes = ','.join(str(i) for i in node_ids) - uri = self.provision_nodes_url.format(env_id=environment_id, - nodes=nodes) - return self.connection.put_request(uri, {}) - - def deploy_nodes(self, environment_id, node_ids, force=False, - noop_run=False): - """Deploy specified nodes for the specified environment.""" - - nodes = ','.join(str(i) for i in node_ids) - uri = self.deploy_nodes_url.format(env_id=environment_id, nodes=nodes, - force=int(force), - noop_run=int(noop_run)) - return self.connection.put_request(uri, {}) - - def redeploy_changes(self, environment_id, dry_run=False, noop_run=False): - env = self._entity_wrapper(obj_id=environment_id) - - redeploy_task = env.redeploy_changes(dry_run=dry_run, - noop_run=noop_run) - return redeploy_task.id - - def spawn_vms(self, environment_id): - env = self._entity_wrapper(obj_id=environment_id) - fuelversion.FuelVersionClient.check_advanced_feature() - return env.spawn_vms() - - def upload_network_template(self, environment_id, - file_path=None): - env = self._entity_wrapper(environment_id) - network_template_data = env.read_network_template_data_from_file( - file_path=file_path) - env.set_network_template_data(network_template_data) - - return file_path - - def download_network_template(self, environment_id, directory=None): - env = self._entity_wrapper(environment_id) - template_data = env.get_network_template_data() - file_path = env.write_network_template_data( - template_data, - directory=directory) - - return file_path - - def delete_network_template(self, environment_id): - env = self._entity_wrapper(environment_id) - env.delete_network_template_data() - - def get_network_configuration(self, environment_id): - env = self._entity_wrapper(environment_id) - return env.get_network_data() - - def set_network_configuration(self, environment_id, new_configuration): - env = self._entity_wrapper(environment_id) - env.set_network_data(new_configuration) - - def verify_network(self, environment_id): - """Start network verification for an environment.""" - - env = self._entity_wrapper(environment_id) - return env.verify_network() - - def get_settings(self, environment_id): - env = self._entity_wrapper(environment_id) - return env.get_settings_data() - - def set_settings(self, environment_id, new_configuration, force=False): - env = self._entity_wrapper(environment_id) - env.set_settings_data(new_configuration, force=force) - - def delete_facts(self, env_id, fact_type): - env = self._entity_wrapper(env_id) - return env.delete_facts(fact_type) - - def download_facts(self, env_id, fact_type, default=False, **kwargs): - env = self._entity_wrapper(env_id) - return env.get_facts(fact_type, default=default, **kwargs) - - def upload_facts(self, env_id, fact_type, facts): - env = self._entity_wrapper(env_id) - return env.upload_facts(fact_type, facts) - - def reset(self, env_id, force=False): - env = self._entity_wrapper(obj_id=env_id) - return env.reset(force) - - def stop(self, env_id): - env = self._entity_wrapper(obj_id=env_id) - return env.stop() - - -def get_client(connection): - return EnvironmentClient(connection) diff --git a/fuelclient/v1/extension.py b/fuelclient/v1/extension.py deleted file mode 100644 index e7e427ed..00000000 --- a/fuelclient/v1/extension.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class ExtensionClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Extension - - def get_by_id(self, environment_id): - ext_obj = self._entity_wrapper(environment_id) - return {'extensions': ', '.join(ext_obj.get_env_extensions())} - - def enable_extensions(self, environment_id, extensions): - ext_obj = self._entity_wrapper(environment_id) - return ext_obj.enable_env_extensions(extensions) - - def disable_extensions(self, environment_id, extensions): - ext_obj = self._entity_wrapper(environment_id) - return ext_obj.disable_env_extensions(extensions) - - -def get_client(connection): - return ExtensionClient(connection) diff --git a/fuelclient/v1/fuelversion.py b/fuelclient/v1/fuelversion.py deleted file mode 100644 index 3e8fd8a7..00000000 --- a/fuelclient/v1/fuelversion.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.cli import error -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class FuelVersionClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.FuelVersion - - @classmethod - def check_advanced_feature(cls): - if 'advanced' not in cls._entity_wrapper.get_feature_groups(): - msg = "Advanced feature should be enabled in feature groups" - raise error.ActionException(msg) - - -def get_client(connection): - return FuelVersionClient(connection) diff --git a/fuelclient/v1/graph.py b/fuelclient/v1/graph.py deleted file mode 100644 index e87131f2..00000000 --- a/fuelclient/v1/graph.py +++ /dev/null @@ -1,296 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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 re -import six - -from fuelclient.cli import error -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class GraphClient(base_v1.BaseV1Client): - _entity_wrapper = objects.Environment - - related_graphs_list_api_path = "{related_model}/{related_model_id}" \ - "/deployment_graphs/" - - related_graph_api_path = "{related_model}/{related_model_id}" \ - "/deployment_graphs/{graph_type}" - - graphs_list_api = "graphs/" - cluster_deploy_api_path = "graphs/execute/" - - cluster_own_tasks_api_path = "clusters/{env_id}/deployment_tasks/own/" - - merged_cluster_tasks_api_path = "clusters/{env_id}/deployment_tasks/" - - merged_plugins_tasks_api_path = "clusters/{env_id}/deployment_tasks/" \ - "plugins/" - - cluster_release_tasks_api_path = "clusters/{env_id}/deployment_tasks/" \ - "release/" - - def update_graph_for_model( - self, data, related_model, related_model_id, graph_type): - return self.connection.put_request( - self.related_graph_api_path.format( - related_model=related_model, - related_model_id=related_model_id, - graph_type=graph_type), - data - ) - - def create_graph_for_model( - self, data, related_model, related_model_id, graph_type): - return self.connection.post_request( - self.related_graph_api_path.format( - related_model=related_model, - related_model_id=related_model_id, - graph_type=graph_type), - data - ) - - def get_graph_for_model( - self, related_model, related_model_id, graph_type): - return self.connection.get_request( - self.related_graph_api_path.format( - related_model=related_model, - related_model_id=related_model_id, - graph_type=graph_type)) - - def upload(self, data, related_model, related_id, graph_type): - # create or update - if not isinstance(data, dict): - data = {'tasks': data} - - method = self.update_graph_for_model - # FIXME(bgaifullin) need to remove loading whole graph only - # for detecting that it does not exist - try: - self.get_graph_for_model(related_model, related_id, graph_type) - except error.HTTPError as exc: - if '404' in exc.message: - method = self.create_graph_for_model - - # could accept {tasks: [], metadata: {}} or just tasks list - method(data, related_model, related_id, graph_type) - - def execute(self, env_id, nodes=None, graph_types=None, task_names=None, - subgraphs=None, **kwargs): - request_data = {'cluster': env_id} - - def map_args_to_graph_types(graph): - result = dict() - result['type'] = graph - if nodes: - result['nodes'] = nodes - if task_names: - result['tasks'] = task_names - return result - - def munge_subgraphs(subgraph): - regexp = re.compile("^([\w\-,]+(?:\/(?:(?:\d+(?:,|-)?)+))?)" - "?(:[\w\-,]+(?:\/(?:(?:\d+(?:,|-)?)+))?)?$") - result = regexp.match(subgraph) - start_vertex = None - end_vertex = None - if result: - if result.group(1): - start_vertex = result.group(1) - if result.group(2): - end_vertex = result.group(2)[1:] - return {'start': [start_vertex], 'end': [end_vertex]} - - if graph_types: - request_data['graphs'] = list(six.moves.map( - map_args_to_graph_types, graph_types - )) - - if subgraphs: - request_data['subgraphs'] = list( - six.moves.map(lambda s: munge_subgraphs(s), subgraphs)) - - request_data.update(kwargs) - - deploy_data = self.connection.post_request( - self.cluster_deploy_api_path, - request_data - ) - return objects.DeployTask.init_with_data(deploy_data) - - def get_merged_cluster_tasks(self, env_id, graph_type=None): - params = {} - if graph_type is not None: - params['graph_type'] = graph_type - - return self.connection.get_request( - self.merged_cluster_tasks_api_path.format(env_id=env_id), - params=params - ) - - def get_merged_plugins_tasks(self, env_id, graph_type=None): - params = {} - if graph_type is not None: - params['graph_type'] = graph_type - - return self.connection.get_request( - self.merged_plugins_tasks_api_path.format(env_id=env_id), - params=params - ) - - def get_release_tasks_for_cluster(self, env_id, graph_type=None): - params = {} - if graph_type is not None: - params['graph_type'] = graph_type - - return self.connection.get_request( - self.cluster_release_tasks_api_path.format(env_id=env_id), - params=params - ) - - def get_own_tasks_for_cluster(self, env_id, graph_type=None): - params = {} - if graph_type is not None: - params['graph_type'] = graph_type - - return self.connection.get_request( - self.cluster_own_tasks_api_path.format(env_id=env_id), - params=params - ) - - def download(self, env_id, level, graph_type): - tasks_levels = { - 'all': lambda: self.get_merged_cluster_tasks( - env_id=env_id, graph_type=graph_type), - - 'cluster': lambda: self.get_own_tasks_for_cluster( - env_id=env_id, graph_type=graph_type), - - 'plugins': lambda: self.get_merged_plugins_tasks( - env_id=env_id, graph_type=graph_type), - - 'release': lambda: self.get_release_tasks_for_cluster( - env_id=env_id, graph_type=graph_type) - } - return tasks_levels[level]() - - def get_env_release_graphs_list(self, env_id): - """Get list of graphs related to the environment's release. - - :param env_id: environment ID - :type env_id: int - :return: list of graphs records - :rtype: list[dict] - """ - data = self.get_by_id(env_id) - release_id = data['release_id'] - return self.connection.get_request( - self.related_graphs_list_api_path.format( - related_model='releases', - related_model_id=release_id - ), params={'fetch_related': '0'} - ) - - def get_env_cluster_graphs_list(self, env_id, fetch_related=True): - """Get list of graphs related to the environment. - - :param env_id: environment ID - :type env_id: int - :param fetch_related: fetch graphs related to - cluster plugins and release - :type fetch_related: bool - - :return: list of graphs records - :rtype: list[dict] - """ - return self.connection.get_request( - self.related_graphs_list_api_path.format( - related_model='clusters', - related_model_id=env_id, - ), params={'fetch_related': '1' if fetch_related else '0'} - ) - - def get_env_plugins_graphs_list(self, env_id): - """Get list of graphs related to plugins active for the - - given environment. - - :param env_id: environment ID - :type env_id: int - :return: list of graphs records - :rtype: list[dict] - """ - env = objects.Environment(env_id) - enabled_plugins_ids = env.get_enabled_plugins() - result = [] - for plugin_id in enabled_plugins_ids: - result += self.connection.get_request( - self.related_graphs_list_api_path.format( - related_model='plugins', - related_model_id=plugin_id - ), params={'fetch_related': '0'} - ) - return result - - def get_all_graphs_list(self): - return self.connection.get_request(self.graphs_list_api) - - def list(self, env_id=None, filters=None): - """Get graphs list. - - If all filter flags are set to False, then it fill be considered as - 'show all' and all filter flags will be toggled to True. - - :param env_id: environment ID - :type env_id: int - :param filters: the name of models which graphs will be included - to result - :return: list of graphs records - :rtype: list[dict] - """ - # we cannot use dict here, because order is important - handlers = ( - ('release', self.get_env_release_graphs_list), - ('plugin', self.get_env_plugins_graphs_list), - ('cluster', self.get_env_cluster_graphs_list) - ) - - graphs_list = [] - filters = filters and set(filters) - - if env_id: - for relation, handler in handlers: - if not filters or relation in filters: - graphs_list.extend(handler(env_id=env_id)) - else: - all_graphs_list = self.get_all_graphs_list() - for graph in all_graphs_list: - for relation in graph['relations']: - if not filters or relation['model'] in filters: - graphs_list.append(graph) - break - - return graphs_list - - def delete(self, related_model, related_id, graph_type): - return self.connection.delete_request( - self.related_graph_api_path.format(related_model=related_model, - related_model_id=related_id, - graph_type=graph_type)) - - -def get_client(connection): - return GraphClient(connection) diff --git a/fuelclient/v1/health.py b/fuelclient/v1/health.py deleted file mode 100644 index f9ebda2d..00000000 --- a/fuelclient/v1/health.py +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 fuelclient.cli import error -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class HealthClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Health - _allowed_statuses = ( - 'error', - 'operational', - 'update_error', - ) - - def get_all(self, environment_id): - """Get list of test sets for a given environment. - - :param environment_id: Id of environment - :type environment_id: int - :return: health test sets as a list of dict - :rtype: list - """ - return self._entity_wrapper.get_test_sets(environment_id) - - def get_status_all(self, environment_id=None): - """Get test sets statuses. If environment_id is None then statuses of - all test sets will be retrieved. - - :param environment_id: Id of environment - :type environment_id: int - :return: health test sets as a list of dict - :rtype: list - """ - data = self._entity_wrapper.get_tests_status_all() - # OSTF API doesn't support filtering by cluster, then do it 'manually' - if environment_id is not None: - data = [i for i in data if i['cluster_id'] == environment_id] - return data - - def get_status_single(self, testset_id): - testrun_obj = self._entity_wrapper(testset_id) - data = testrun_obj.get_tests_status_single() - if data: - result = [] - # Retrieve and re-format 'tests' from nested data for clarity - for tests in data.get('tests'): - result.append("\n* {} - {}, ('{}')".format(tests["status"], - tests["name"], - tests["message"])) - else: - msg = "Test sets with id {0} does not exist".format(testset_id) - raise error.ActionException(msg) - data['tests'] = ' '.join(result) - return data - - def get_last_test_status(self, environment_id): - return self._entity_wrapper.get_last_tests_status(environment_id) - - def start(self, environment_id, ostf_credentials=None, test_sets=None, - force=False): - """Run test sets for a given environment. If test_sets is None then - all test sets will be run - - :param environment_id: Id of environment - :type environment_id: int - :param ostf_credentials: ostf credentials - :type ostf_credentials: dict - :param test_sets: list of test sets - :type test_sets: list - :param force: - :type force: bool - :return: running health test sets as a list of dict - :rtype: list - """ - env_obj = objects.Environment(environment_id) - - if env_obj.status not in self._allowed_statuses and not force: - raise error.EnvironmentException( - "Environment is not ready to run health check " - "because it is in '{0}' state. Health check is likely " - "to fail because of this. Use '--force' flag " - "to proceed anyway.".format(env_obj.status) - ) - - if env_obj.is_customized and not force: - raise error.EnvironmentException( - "Environment deployment facts were updated. " - "Health check is likely to fail because of " - "that. Use '--force' flag to proceed anyway." - ) - test_sets_to_run = test_sets or set(ts['id'] for ts in - self.get_all(environment_id)) - - return self._entity_wrapper.run_test_sets(environment_id, - test_sets_to_run, - ostf_credentials) - - def action(self, testrun_id, action_status): - """Make an action on specific test set. - - :param testrun_id: id of test set - :type testrun_id: int - :param action_status: the type of action ('stopped', 'restarted') - :type action_status: str - """ - testrun_obj = self._entity_wrapper(obj_id=testrun_id) - return testrun_obj.action_test(action_status)[0] - - -def get_client(connection): - return HealthClient(connection) diff --git a/fuelclient/v1/network_configuration.py b/fuelclient/v1/network_configuration.py deleted file mode 100644 index d4790f0a..00000000 --- a/fuelclient/v1/network_configuration.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class NetworkConfigurationClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Task - - def download(self, transaction_id): - task = self._entity_wrapper(transaction_id) - return task.network_configuration() - - -def get_client(connection): - return NetworkConfigurationClient(connection) diff --git a/fuelclient/v1/network_group.py b/fuelclient/v1/network_group.py deleted file mode 100644 index ff375b12..00000000 --- a/fuelclient/v1/network_group.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient.cli import error -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class NetworkGroupClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.NetworkGroup - - updatable_attributes = ( - 'name', 'vlan', 'cidr', 'gateway', 'group_id', 'meta') - - def create(self, name, release, vlan, cidr, - gateway, group_id, meta=None): - net_group = self._entity_wrapper.create( - name, release, vlan, cidr, gateway, group_id, meta) - return net_group.data - - def update(self, network_id, **kwargs): - for attr in kwargs: - if attr not in self.updatable_attributes: - raise error.BadDataException( - 'Update of attribute "{0}" is not allowed'.format(attr)) - - net_group = self._entity_wrapper(network_id) - net_group.set(kwargs) - - return net_group.data - - def delete_by_id(self, network_id): - env_obj = self._entity_wrapper(network_id) - env_obj.delete() - - -def get_client(connection): - return NetworkGroupClient(connection) diff --git a/fuelclient/v1/node.py b/fuelclient/v1/node.py deleted file mode 100644 index aa2fa710..00000000 --- a/fuelclient/v1/node.py +++ /dev/null @@ -1,320 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from collections import namedtuple -import copy - -from fuelclient.cli import error -from fuelclient import objects -from fuelclient.v1 import base_v1 -from fuelclient.v1 import fuelversion - - -SplittedLabel = namedtuple('SplittedLabel', ['key', 'value', 'has_separator']) - - -class NodeClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Node - _updatable_attributes = ('hostname', 'labels', 'name') - - def get_all(self, environment_id=None, labels=None): - """Get nodes by specific environment or labels - - :param environment_id: Id of specific environment(cluster) - :type environment_id: int - :param labels: List of string labels for filtering nodes - :type labels: list - :returns: list -- filtered list of nodes - """ - if environment_id is not None: - result = self._entity_wrapper.get_by_env_id( - cluster_id=environment_id) - else: - result = self._entity_wrapper.get_all_data() - - if labels: - result = [item for item in result - if self._check_label(labels, item)] - - return result - - def undiscover_nodes(self, env_id=None, node_id=None, force=False): - """Delete nodes from database. If node_id is None then all nodes - from specified environment will be deleted. - - :param env_id: Id of env to delete nodes from database - :type env_id: int - :param node_id: Id of node to delete from database - :type node_id: int - :param force: Forces deletion of nodes regardless of their state - :type force: bool - :returns: list -- ids of nodes that were deleted from database - """ - nodes = [] - if node_id is not None: - nodes.append(self._entity_wrapper(obj_id=node_id).data) - elif env_id is not None: - nodes.extend(self.get_all(environment_id=env_id)) - if not nodes: - raise error.ActionException( - "Cluster with id {0} does not exist or " - "does not contain any nodes".format(env_id) - ) - else: - raise ValueError('Expected either env_id or node_id args') - - # If 'force' flag is not specified then check nodes status - if not force: - online_nodes = [node for node in nodes if node['online']] - if online_nodes: - raise error.ActionException( - "Nodes with ids {0} cannot be deleted from database " - "because they are online. You might want to use the " - "--force option.".format( - [node['id'] for node in online_nodes])) - - node_ids = [node['id'] for node in nodes] - objects.NodeCollection.delete_by_ids(node_ids) - return node_ids - - def get_node_vms_conf(self, node_id): - node = self._entity_wrapper(node_id) - fuelversion.FuelVersionClient.check_advanced_feature() - return node.get_node_vms_conf() - - def node_vms_create(self, node_id, config): - node = self._entity_wrapper(node_id) - fuelversion.FuelVersionClient.check_advanced_feature() - return node.node_vms_create(config) - - def update(self, node_id, **updated_attributes): - node = self._entity_wrapper(obj_id=node_id) - - for attr in updated_attributes: - if attr not in self._updatable_attributes: - msg = 'Only {0} are updatable'.format( - self._updatable_attributes) - raise error.BadDataException(msg) - - return node.set(updated_attributes) - - def get_all_labels_for_nodes(self, node_ids=None): - """Get list of labels for specific nodes. If no node_ids then all - labels should be returned - - :param node_ids: List of node ids for filtering labels - :type node_ids: list - :returns: list -- filtered list of labels - """ - labels = [] - - result = self._entity_wrapper.get_all_data() - - if node_ids: - result = filter(lambda node: str(node['id']) in node_ids, result) - - for node in result: - for key, value in node.get('labels', []).items(): - labels.append({ - 'node_id': node.get('id'), - 'label_name': key, - 'label_value': value - }) - - return labels - - def set_labels_for_nodes(self, labels=None, node_ids=None): - """Update nodes labels attribute with new data. If node_ids - are empty list then labels will be updated on all nodes - - :param labels: List of string pairs `key=val` for labels - :type labels: list - :param node_ids: List of node ids where labels should be updated - :type node_ids: list - :return: list -- ids of nodes where labels were updated - """ - data_to_return = [] - labels_to_update = {} - - for label in labels: - key, val, _ = self._split_label(label) - if not key: - msg = 'Wrong label "{0}" was provided. Label key couldn\'t ' \ - 'be an empty string.'.format(label) - raise error.LabelEmptyKeyError(msg) - labels_to_update[key] = val - - if node_ids: - for node_id in node_ids: - node = self._entity_wrapper(obj_id=node_id) - db_labels = copy.deepcopy(node.labels) - db_labels.update(labels_to_update) - - result = self.update(node_id, **{'labels': db_labels}) - data_to_return.append(str(result.get('id'))) - else: - nodes = self._entity_wrapper.get_all_data() - for node in nodes: - db_labels = copy.deepcopy(node['labels']) - db_labels.update(labels_to_update) - - result = self.update(node['id'], **{'labels': db_labels}) - data_to_return.append(str(result.get('id'))) - - return data_to_return - - def delete_labels_for_nodes(self, labels=None, node_ids=None): - """Delete labels data from nodes labels. If node_ids are - empty list then labels will be deleted on all nodes - - :param labels: List of string label keys - :type labels: list - :param node_ids: List of node ids where labels should be deleted - :type node_ids: list - :returns: list -- ids of nodes where labels were deleted - """ - data_to_return = [] - - if node_ids: - nodes = (self._entity_wrapper(obj_id=n_id).data - for n_id in node_ids) - else: - nodes = self._entity_wrapper.get_all_data() - - for node in nodes: - updated_labels = self._labels_after_delete( - node['labels'], labels) - - result = self.update(node['id'], **{'labels': updated_labels}) - data_to_return.append(str(result.get('id'))) - - return data_to_return - - def download_attributes(self, node_id, directory=None): - node = self._entity_wrapper(node_id) - attributes = node.get_node_attributes() - return node.write_attribute( - 'attributes', attributes, directory=directory) - - def get_disks(self, node_id): - """Download configuration of disks for a node - - :param node_id: Id of a node. - :return: dict with the configuration of disks for the node. - - """ - node = self._entity_wrapper(node_id) - return node.get_attribute('disks') - - def get_default_disks(self, node_id): - """Download default configuration of disks for a node - - :param node_id: Id of a node. - :return: dict with the default configuration of disks - for the node. - - """ - node = self._entity_wrapper(node_id) - return node.get_default_attribute('disks') - - def set_disks(self, node_id, disks): - """Upload and set configuration of disks for a node - - :param node_id: Id of a node. - :param interfaces: dict that contains valid configuration - for disks - - """ - node = self._entity_wrapper(node_id) - return node.upload_node_attribute('disks', disks) - - def upload_attributes(self, node_id, directory=None): - node = self._entity_wrapper(node_id) - attributes = node.read_attribute('attributes', directory=directory) - node.update_node_attributes(attributes) - - def get_interfaces(self, node_id): - """Download configuration of interfaces for a node - - :param node_id: Id of a node. - :return: dict with the configuration of interfaces for the node. - - """ - node = self._entity_wrapper(node_id) - return node.get_attribute('interfaces') - - def get_default_interfaces(self, node_id): - """Download default configuration of interfaces for a node - - :param node_id: Id of a node. - :return: dict with the configuration of interfaces for the node. - - """ - node = self._entity_wrapper(node_id) - return node.get_default_attribute('interfaces') - - def set_interfaces(self, node_id, interfaces): - """Upload and set configuration of interfaces for a node - - :param node_id: Id of a node. - :param interfaces: dict that contains valid configuration - for interfaces - - """ - node = self._entity_wrapper(node_id) - return node.upload_node_attribute('interfaces', interfaces) - - def _check_label(self, labels, item): - checking_list = [] - - for label in labels: - key, val, has_separator = self._split_label(label) - if key in item.get('labels'): - if not has_separator: - checking_val = True - else: - checking_val = item['labels'][key] == val - checking_list.append(checking_val) - - return any(checking_list) - - @classmethod - def _labels_after_delete(cls, labels, labels_to_delete): - if not labels_to_delete: - return {} - - db_labels = copy.deepcopy(labels) - for label in labels_to_delete: - label = label.strip() - sl = cls._split_label(label) - if sl.has_separator: - if sl.key in db_labels and db_labels[sl.key] == sl.value: - db_labels.pop(sl.key) - else: - db_labels.pop(sl.key, None) - - return db_labels - - @staticmethod - def _split_label(label): - name, separator, value = label.partition('=') - name = name.strip() - value = value.strip() - value = None if value == '' else value - return SplittedLabel(name, value, bool(separator)) - - -def get_client(connection): - return NodeClient(connection) diff --git a/fuelclient/v1/openstack_config.py b/fuelclient/v1/openstack_config.py deleted file mode 100644 index 414977a2..00000000 --- a/fuelclient/v1/openstack_config.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class OpenstackConfigClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.OpenstackConfig - - def upload(self, path, cluster_id, node_ids=None, node_role=None): - data = self._entity_wrapper.read_file(path) - configuration = data['configuration'] - - config_obj = self._entity_wrapper.create(cluster_id=cluster_id, - configuration=configuration, - node_ids=node_ids, - node_role=node_role) - return [obj.data for obj in config_obj] - - def download(self, config_id, path): - config = self._entity_wrapper(config_id) - config.write_file(path, { - 'configuration': config.data['configuration']}) - - return path - - def execute(self, cluster_id, config_id=None, node_ids=None, - node_role=None, force=False): - task = self._entity_wrapper.execute(cluster_id=cluster_id, - config_id=config_id, - node_ids=node_ids, - node_role=node_role, - force=force) - - return task.data - - def get_filtered(self, cluster_id, node_ids=None, - node_role=None, is_active=True): - return self._entity_wrapper.get_filtered_data( - cluster_id=cluster_id, node_ids=node_ids, - node_role=node_role, is_active=is_active) - - def delete(self, config_id): - config = self._entity_wrapper(config_id) - config.delete() - - -def get_client(connection): - return OpenstackConfigClient(connection) diff --git a/fuelclient/v1/plugins.py b/fuelclient/v1/plugins.py deleted file mode 100644 index 904ca3db..00000000 --- a/fuelclient/v1/plugins.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2015 Mirantis, 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 collections -import six - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class PluginsClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Plugins - - def get_all(self): - """Get plugins data and re-format 'releases' info to display - supported 'os', 'version' in a user-friendly way, e.g.: - ubuntu (liberty-8.0, liberty-9.0, mitaka-9.0) - centos (liberty-8.0), ubuntu (liberty-8.0) - - :returns: list of plugins - :rtype: list - """ - # Replace original nested 'releases' dictionary (from plugins meta - # dictionary) to a new user-friendly form with releases info, i.e. - # 'os', 'version' that specific plugin supports - plugins = self._entity_wrapper.get_all_data() - for plugin in plugins: - releases = collections.defaultdict(list) - for key in plugin['releases']: - releases[key['os']].append(key['version']) - plugin['releases'] = ', '.join('{} ({})'.format(k, ', '.join(v)) - for k, v in six.iteritems(releases)) - return plugins - - def sync(self, ids): - """Synchronise plugins on file system with plugins in API service. - - :param ids: List of ids for filtering plugins - :type ids: list - """ - - self._entity_wrapper.sync(plugin_ids=ids) - - def install(self, plugin_path, force=False): - """Install plugin archive and register in API service. - - :param plugin_path: Path to plugin file - :type plugin_path: str - :param force: Update existent plugin even if it is not updatable - :type force: bool - """ - return self._entity_wrapper.install(plugin_path, force=force) - - def remove(self, plugin_name, plugin_version): - """Remove the plugin package, and update data in API service. - - :param str plugin_name: Name of plugin to remove - :param str plugin_version: Version of plugin to remove - """ - return self._entity_wrapper.remove(plugin_name, plugin_version) - - -def get_client(connection): - return PluginsClient(connection) diff --git a/fuelclient/v1/release.py b/fuelclient/v1/release.py deleted file mode 100644 index 5554c1e9..00000000 --- a/fuelclient/v1/release.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class ReleaseClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Release - - def update_attributes_metadata_by_id(self, release_id, data): - release_obj = self._entity_wrapper(obj_id=release_id) - release_obj.update_attributes_metadata(data) - - def get_attributes_metadata_by_id(self, release_id): - release_obj = self._entity_wrapper(obj_id=release_id) - return release_obj.get_attributes_metadata() - - def get_components_by_id(self, release_id): - release_obj = self._entity_wrapper(obj_id=release_id) - return release_obj.get_components() - - -def get_client(connection): - return ReleaseClient(connection) diff --git a/fuelclient/v1/role.py b/fuelclient/v1/role.py deleted file mode 100644 index f38fe4cf..00000000 --- a/fuelclient/v1/role.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 fuelclient import objects -from fuelclient.v1 import base_v1 - - -class RoleClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Role - - def get_all(self, owner_type, owner_id): - """Get all available roles for specific release or cluster. - - :param owner_type: release or cluster - :type owner_id: int - :return: roles data as a list of dict - :rtype: list - """ - - data = self._entity_wrapper(owner_type, owner_id).get_all() - - # Retrieve nested data from 'meta' and add it as a new key-value pair - for role in data: - role_meta = role.pop('meta') - role['group'] = role_meta.get('group') - role['conflicts'] = role_meta.get('conflicts') - role['description'] = role_meta.get('description') - - return data - - def get_one(self, owner_type, owner_id, role_name): - role = self._entity_wrapper(owner_type, owner_id) - return role.get_role(role_name) - - def update(self, data, **kwargs): - role = self._entity_wrapper(owner_type=kwargs['owner_type'], - owner_id=kwargs['owner_id']) - return role.update_role(kwargs['role_name'], data) - - def create(self, data, **kwargs): - role = self._entity_wrapper(owner_type=kwargs['owner_type'], - owner_id=kwargs['owner_id']) - return role.create_role(data) - - def delete(self, owner_type, owner_id, role_name): - role = self._entity_wrapper(owner_type=owner_type, - owner_id=owner_id) - return role.delete_role(role_name) - - -def get_client(connection): - return RoleClient(connection) diff --git a/fuelclient/v1/sequence.py b/fuelclient/v1/sequence.py deleted file mode 100644 index 7d5fc35d..00000000 --- a/fuelclient/v1/sequence.py +++ /dev/null @@ -1,107 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class SequenceClient(base_v1.BaseV1Client): - _entity_wrapper = objects.Sequence - - executor_path = _entity_wrapper.instance_api_path + 'execute/' - - def create(self, release_id, name, graph_types): - """Creates new sequence object. - - :param release_id: the release object id - :param name: the sequence name - :param graph_types: the types of graphs - :returns: created object - """ - data = {'name': name} - graphs = data['graphs'] = [] - for graph_type in graph_types: - graphs.append({'type': graph_type}) - - return self.upload(release_id, data) - - def upload(self, release_id, data): - """Creates new sequence object from data. - - :param release_id: release object id - :param data: the sequence properties - :returns: created object - """ - url = self._entity_wrapper.class_api_path - data['release'] = release_id - return self.connection.post_request(url, data) - - def download(self, sequence_id): - """Get raw content of sequence.""" - return super(SequenceClient, self).get_by_id(sequence_id) - - def update(self, sequence_id, name=None, graph_types=None): - """Updates existing object. - - :param sequence_id: the sequence object id - :param name: new name - :param graph_types: new graph types - :returns: updated object or False if nothing to update - """ - data = {} - if name: - data['name'] = name - if graph_types: - graphs = data['graphs'] = [] - for graph_type in graph_types: - graphs.append({'type': graph_type}) - - if not data: - return False - - url = self._entity_wrapper.instance_api_path.format(sequence_id) - return self.connection.put_request(url, data) - - def get_by_id(self, sequence_id): - """Gets formatted sequence data by id.""" - data = super(SequenceClient, self).get_by_id(sequence_id) - data['graphs'] = ', '.join(g['type'] for g in data['graphs']) - return data - - def delete_by_id(self, sequence_id): - """Deletes existed object. - - :param sequence_id: the sequence object id - """ - url = self._entity_wrapper.instance_api_path.format(sequence_id) - self.connection.delete_request(url) - - def execute(self, sequence_id, env_id, **kwargs): - """Executes sequence on cluster. - - :param sequence_id: the sequence object id - :param env_id: the cluster id - :param kwargs: options - force, dry_run and noop. - """ - data = {'cluster': env_id} - data.update(kwargs) - url = self.executor_path.format(sequence_id) - deploy_data = self.connection.post_request(url, data) - return objects.DeployTask.init_with_data(deploy_data) - - -def get_client(connection): - return SequenceClient(connection) diff --git a/fuelclient/v1/snapshot.py b/fuelclient/v1/snapshot.py deleted file mode 100644 index 6ca2a12f..00000000 --- a/fuelclient/v1/snapshot.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Vitalii Kulanov -# -# 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 fuelclient import objects -from fuelclient.v1 import base_v1 - - -class SnapshotClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.SnapshotTask - - def create_snapshot(self, config): - return self._entity_wrapper.start_snapshot_task(config) - - def get_default_config(self): - return self._entity_wrapper.get_default_config() - - -def get_client(connection): - return SnapshotClient(connection) diff --git a/fuelclient/v1/tag.py b/fuelclient/v1/tag.py deleted file mode 100644 index ae6fdf6e..00000000 --- a/fuelclient/v1/tag.py +++ /dev/null @@ -1,57 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class TagClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Tag - - def get_all(self, owner_type, owner_id): - """Get all available tags for specific release or cluster. - - :param owner_type: release or cluster - :type owner_id: int - :return: tags data as a list of dict - :rtype: list - """ - tags = self._entity_wrapper(owner_type, owner_id).get_all() - return tags - - def get_tag(self, owner_type, owner_id, tag_name=''): - tag = self._entity_wrapper(owner_type, owner_id) - return tag.get_tag(tag_name) - - def update(self, data, **kwargs): - tag = self._entity_wrapper(owner_type=kwargs['owner_type'], - owner_id=kwargs['owner_id']) - return tag.update_tag(kwargs['tag_name'], data) - - def create(self, data, **kwargs): - tag = self._entity_wrapper(owner_type=kwargs['owner_type'], - owner_id=kwargs['owner_id']) - return tag.create_tag(data) - - def delete(self, owner_type, owner_id, tag_name): - tag = self._entity_wrapper(owner_type=owner_type, owner_id=owner_id) - return tag.delete_tag(tag_name) - - -def get_client(connection): - return TagClient(connection) diff --git a/fuelclient/v1/task.py b/fuelclient/v1/task.py deleted file mode 100644 index 3c80582a..00000000 --- a/fuelclient/v1/task.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2015 Mirantis, 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. - -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class TaskClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Task - - def delete_by_id(self, task_id, force=False): - """Delete a given task by its id - - :param task_id: Id of a task to delete. - :type task_id: int - :param force: Force deletion of a task without - considering its state - - """ - task_obj = self._entity_wrapper(obj_id=task_id) - task_obj.delete(force=force) - - -def get_client(connection): - return TaskClient(connection) diff --git a/fuelclient/v1/vip.py b/fuelclient/v1/vip.py deleted file mode 100644 index 66aefd26..00000000 --- a/fuelclient/v1/vip.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2016 Mirantis, 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. - -from fuelclient.cli.serializers import Serializer -from fuelclient import objects -from fuelclient.v1 import base_v1 - - -class VipClient(base_v1.BaseV1Client): - - _entity_wrapper = objects.Environment - - @staticmethod - def download(env_id, ip_addr_id=None, network_id=None, - network_role=None, file_path=None): - - env = objects.Environment(env_id) - vips_data = env.get_vips_data( - ip_address_id=ip_addr_id, - network=network_id, - network_role=network_role - ) - vips_data_file_path = env.write_vips_data_to_file( - vips_data, - file_path=file_path, - serializer=Serializer() - ) - return vips_data_file_path - - @staticmethod - def upload(env_id, file_path): - env = objects.Environment(env_id) - vips_data = env.read_vips_data_from_file( - file_path=file_path, - serializer=Serializer() - ) - env.set_vips_data(vips_data) - - @staticmethod - def create(env_id, ip_addr, network, vip_name, vip_namespace=None): - env = objects.Environment(env_id) - vip_data = { - 'ip_addr': ip_addr, - 'network': network, - 'vip_name': vip_name - } - if vip_namespace is not None: - vip_data['vip_namespace'] = vip_namespace - - env.create_vip(**vip_data) - - -def get_client(connection): - return VipClient(connection) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 22ec29b2..00000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -cliff!=1.16.0,>=1.15.0 # Apache-2.0 -oslo.utils>=3.5.0 # Apache-2.0 -pbr>=1.6 # Apache-2.0 -python-keystoneclient!=1.8.0,!=2.1.0,>=1.6.0 # Apache-2.0 -PyYAML>=3.1.0 # MIT -requests!=2.9.0,>=2.8.1 # Apache-2.0 -six>=1.9.0 # MIT diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index eda59dcf..00000000 --- a/setup.cfg +++ /dev/null @@ -1,152 +0,0 @@ -[metadata] -name = python-fuelclient -version = 10.0.0 -summary = Command line interface and Python API wrapper for Fuel. -author = Mirantis Inc. -author-email = product@mirantis.com -home-page = https://docs.fuel-infra.org/fuel-dev -description-file = - README.rst -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - -[files] -packages = - fuelclient - -[entry_points] -console_scripts = - fuel=fuelclient.cli.parser:main - fuel2=fuelclient.main:main - -fuelclient = - env_add_nodes=fuelclient.commands.environment:EnvAddNodes - env_create=fuelclient.commands.environment:EnvCreate - env_delete=fuelclient.commands.environment:EnvDelete - env_deploy=fuelclient.commands.environment:EnvDeploy - env_deployment-facts_delete=fuelclient.commands.environment:EnvDeploymentFactsDelete - env_deployment-facts_download=fuelclient.commands.environment:EnvDeploymentFactsDownload - env_deployment-facts_get-default=fuelclient.commands.environment:EnvDeploymentFactsGetDefault - env_deployment-facts_upload=fuelclient.commands.environment:EnvDeploymentFactsUpload - env_extension_disable=fuelclient.commands.extension:EnvExtensionDisable - env_extension_enable=fuelclient.commands.extension:EnvExtensionEnable - env_extension_show=fuelclient.commands.extension:EnvExtensionShow - env_list=fuelclient.commands.environment:EnvList - env_network_download=fuelclient.commands.environment:EnvNetworkDownload - env_network_upload=fuelclient.commands.environment:EnvNetworkUpload - env_network_verify=fuelclient.commands.environment:EnvNetworkVerify - env_nodes_deploy=fuelclient.commands.environment:EnvDeployNodes - env_nodes_provision=fuelclient.commands.environment:EnvProvisionNodes - env_provisioning-facts_delete=fuelclient.commands.environment:EnvProvisioningFactsDelete - env_provisioning-facts_download=fuelclient.commands.environment:EnvProvisioningFactsDownload - env_provisioning-facts_get-default=fuelclient.commands.environment:EnvProvisioningFactsGetDefault - env_provisioning-facts_upload=fuelclient.commands.environment:EnvProvisioningFactsUpload - env_redeploy=fuelclient.commands.environment:EnvRedeploy - env_remove_nodes=fuelclient.commands.environment:EnvRemoveNodes - env_reset=fuelclient.commands.environment:EnvReset - env_settings_download=fuelclient.commands.environment:EnvSettingsDownload - env_settings_upload=fuelclient.commands.environment:EnvSettingsUpload - env_show=fuelclient.commands.environment:EnvShow - env_spawn-vms=fuelclient.commands.environment:EnvSpawnVms - env_stop-deployment=fuelclient.commands.environment:EnvStopDeploy - env_update=fuelclient.commands.environment:EnvUpdate - extension_list=fuelclient.commands.extension:ExtensionList - fuel-version=fuelclient.commands.fuelversion:FuelVersion - graph_delete=fuelclient.commands.graph:GraphDelete - graph_download=fuelclient.commands.graph:GraphDownload - graph_execute=fuelclient.commands.graph:GraphExecute - graph_list=fuelclient.commands.graph:GraphList - graph_upload=fuelclient.commands.graph:GraphUpload - health_list=fuelclient.commands.health:HealthTestSetsList - health_restart=fuelclient.commands.health:HealthCheckRestart - health_start=fuelclient.commands.health:HealthCheckStart - health_status_list=fuelclient.commands.health:HealthTestSetsStatusList - health_status_show=fuelclient.commands.health:HealthTestSetsStatusShow - health_stop=fuelclient.commands.health:HealthCheckStop - network-group_create=fuelclient.commands.network_group:NetworkGroupCreate - network-group_delete=fuelclient.commands.network_group:NetworkGroupDelete - network-group_list=fuelclient.commands.network_group:NetworkGroupList - network-group_show=fuelclient.commands.network_group:NetworkGroupShow - network-group_update=fuelclient.commands.network_group:NetworkGroupUpdate - network-template_delete=fuelclient.commands.network_template:NetworkTemplateDelete - network-template_download=fuelclient.commands.network_template:NetworkTemplateDownload - network-template_upload=fuelclient.commands.network_template:NetworkTemplateUpload - node_ansible-inventory=fuelclient.commands.node:NodeAnsibleInventory - node_attributes-download=fuelclient.commands.node:NodeAttributesDownload - node_attributes-upload=fuelclient.commands.node:NodeAttributesUpload - node_create-vms-conf=fuelclient.commands.node:NodeCreateVMsConf - node_interfaces_download=fuelclient.commands.node:NodeInterfacesDownload - node_interfaces_get-default=fuelclient.commands.node:NodeInterfacesGetDefault - node_interfaces_upload=fuelclient.commands.node:NodeInterfacesUpload - node_disks_download=fuelclient.commands.node:NodeDisksDownload - node_disks_get-default=fuelclient.commands.node:NodeDisksGetDefault - node_disks_upload=fuelclient.commands.node:NodeDisksUpload - node_label_delete=fuelclient.commands.node:NodeLabelDelete - node_label_list=fuelclient.commands.node:NodeLabelList - node_label_set=fuelclient.commands.node:NodeLabelSet - node_list-vms-conf=fuelclient.commands.node:NodeVmsList - node_list=fuelclient.commands.node:NodeList - node_show=fuelclient.commands.node:NodeShow - node_undiscover = fuelclient.commands.node:NodeUndiscover - node_update=fuelclient.commands.node:NodeUpdate - openstack-config_delete=fuelclient.commands.openstack_config:OpenstackConfigDelete - openstack-config_download=fuelclient.commands.openstack_config:OpenstackConfigDownload - openstack-config_execute=fuelclient.commands.openstack_config:OpenstackConfigExecute - openstack-config_list=fuelclient.commands.openstack_config:OpenstackConfigList - openstack-config_upload=fuelclient.commands.openstack_config:OpenstackConfigUpload - plugins_install=fuelclient.commands.plugins:PluginInstall - plugins_list=fuelclient.commands.plugins:PluginsList - plugins_remove=fuelclient.commands.plugins:PluginRemove - plugins_sync=fuelclient.commands.plugins:PluginsSync - release_component_list=fuelclient.commands.release:ReleaseComponentList - release_list=fuelclient.commands.release:ReleaseList - release_repos_list=fuelclient.commands.release:ReleaseReposList - release_repos_update=fuelclient.commands.release:ReleaseReposUpdate - role_create=fuelclient.commands.role:RoleCreate - role_delete=fuelclient.commands.role:RoleDelete - role_download=fuelclient.commands.role:RoleDownload - role_list=fuelclient.commands.role:RoleList - role_update=fuelclient.commands.role:RoleUpdate - tag_create=fuelclient.commands.tag:TagCreate - tag_delete=fuelclient.commands.tag:TagDelete - tag_download=fuelclient.commands.tag:TagDownload - tag_list=fuelclient.commands.tag:TagList - tag_update=fuelclient.commands.tag:TagUpdate - task_delete=fuelclient.commands.task:TaskDelete - task_deployment-info_download=fuelclient.commands.task:TaskDeploymentInfoDownload - task_history_show=fuelclient.commands.task:TaskHistoryShow - task_list=fuelclient.commands.task:TaskList - task_network-configuration_download=fuelclient.commands.task:TaskNetworkConfigurationDownload - task_settings_download=fuelclient.commands.task:TaskClusterSettingsDownload - task_show=fuelclient.commands.task:TaskShow - sequence_create=fuelclient.commands.sequence:SequenceCreate - sequence_delete=fuelclient.commands.sequence:SequenceDelete - sequence_download=fuelclient.commands.sequence:SequenceDownload - sequence_execute=fuelclient.commands.sequence:SequenceExecute - sequence_list=fuelclient.commands.sequence:SequenceList - sequence_show=fuelclient.commands.sequence:SequenceShow - sequence_update=fuelclient.commands.sequence:SequenceUpdate - sequence_upload=fuelclient.commands.sequence:SequenceUpload - snapshot_create=fuelclient.commands.snapshot:SnapshotGenerate - snapshot_get-default-config=fuelclient.commands.snapshot:SnapshotConfigGetDefault - snapshot_get-link=fuelclient.commands.snapshot:SnapshotGetLink - vip_create=fuelclient.commands.vip:VipCreate - vip_download=fuelclient.commands.vip:VipDownload - vip_upload=fuelclient.commands.vip:VipUpload - -[global] -setup-hooks = - pbr.hooks.setup_hook - fuelclient.hooks.setup_hook - -[wheel] -python-tag = py2 diff --git a/setup.py b/setup.py deleted file mode 100644 index 782bb21f..00000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/specs/python-fuelclient.spec b/specs/python-fuelclient.spec deleted file mode 100644 index 12038e36..00000000 --- a/specs/python-fuelclient.spec +++ /dev/null @@ -1,67 +0,0 @@ -%if 0%{?rhel} && 0%{?rhel} <= 7 -%{!?__python2: %global __python2 /usr/bin/python2} -%{!?python2_sitelib: %global python2_sitelib %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")} -%{!?python2_sitearch: %global python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")} -%endif - -%define name python-fuelclient -%{!?version: %define version 10.0.0} -%{!?release: %define release 1} - -Summary: Console utility for working with fuel rest api -Name: %{name} -Version: %{version} -Release: %{release} -Source0: %{name}-%{version}.tar.gz -License: Apache -Group: Development/Libraries -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot -Prefix: %{_prefix} - -BuildArch: noarch - -BuildRequires: python-setuptools -BuildRequires: python-pbr >= 1.8.0 - -%if 0%{!?rhel:0} == 6 -Requires: python-argparse -%endif - -Conflicts: python-requests == 2.8.0 - -Requires: perl -Requires: python-cliff >= 1.14.0 -Requires: python-pbr >= 1.6 -Requires: python-keystoneclient >= 1.6.0 -Requires: PyYAML >= 3.1.0 -Requires: python-requests >= 2.5.2 -Requires: python-six >= 1.9.0 - - -Requires: bash-completion - -%description -Summary: Console utility for working with fuel rest api - -%prep -%setup -cq -n %{name}-%{version} - -%build -cd %{_builddir}/%{name}-%{version} && %{__python2} setup.py build - -%install -rm -rf $RPM_BUILD_ROOT -cd %{_builddir}/%{name}-%{version} && %{__python2} setup.py install --single-version-externally-managed -O1 --root=$RPM_BUILD_ROOT - -%post -# FIXME(mkwiek): fix fuelclient to generate usable autocomplete bash -fuel2 complete | perl -pe "s/-(?=.*=')/_/g" | perl -pe 's;(?<=cmds_\$\{)proposed;proposed//-/_;g' | sed -e "s/local cur prev words/local -a words/g" > %{_datadir}/bash-completion/completions/fuel2 - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root) -%{python2_sitelib}/* -%{_bindir}/* -%doc fuelclient/fuel_client.yaml diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index 9186cd6d..00000000 --- a/test-requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -os-testr>=0.4.1 # Apache-2.0 -coverage>=3.6 # Apache-2.0 -fixtures>=1.3.1 # Apache-2.0/BSD -hacking>=0.12.0,!=0.13.0,<0.14 # Apache-2.0 -mock>=1.2 # BSD -oslotest>=1.10.0 # Apache-2.0 -requests-mock>=0.7.0 # Apache-2.0 -testrepository>=0.0.18 # Apache-2.0/BSD -testtools>=1.4.0 # MIT - -# Files beyond this line are not in Global Requirements list -# and must be added there. -pyprof2calltree>=1.3.2 -gprof2dot>=2014.09.29 diff --git a/tools/env.sh b/tools/env.sh deleted file mode 100755 index 96dbe281..00000000 --- a/tools/env.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# Copyright 2016 Mirantis, 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. - -set -eu - -. $(dirname $0)/env_functions.sh - -case $1 in - prepare_nailgun) - prepare_nailgun - ;; - cleanup_nailgun) - cleanup_nailgun - ;; - prepare_fuelclient) - prepare_fuelclient_config - ;; - cleanup_fuelclient) - cleanup_fuelclient_config - ;; - prepare_fuel_web_repo) - prepare_fuel_web_repo - ;; - cleanup_fuel_web_repo) - cleanup_fuel_web_repo - ;; - *) - echo "Not supported subcommand. Available subcommands: " - echo "cleanup_nailgun" - echo "prepare_nailgun" - echo "cleanup_fuelclient" - echo "prepare_fuelclient" - echo "cleanup_fuel_web_repo" - echo "prepare_fuel_web_repo" - exit 1 - ;; -esac diff --git a/tools/env_functions.sh b/tools/env_functions.sh deleted file mode 100644 index 466ee5f7..00000000 --- a/tools/env_functions.sh +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright 2016 Mirantis, 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. - -function cleanup_nailgun { - echo "Cleaning up nailgun." - pushd "$FUEL_WEB_ROOT" > /dev/null - tox -e stop || echo "Error while stopping nailgun." - popd > /dev/null - - pushd "$FUEL_WEB_ROOT" > /dev/null - tox -e cleanup - popd > /dev/null -} - -function prepare_nailgun { - echo "Preparing nailgun." - pushd "$FUEL_WEB_ROOT" > /dev/null - tox -e start - popd > /dev/null -} - -function prepare_fuelclient_config { - echo "Creating fuelclient config file $FUELCLIENT_CUSTOM_SETTINGS" - mkdir -p $(dirname $FUELCLIENT_CUSTOM_SETTINGS) - cat > $FUELCLIENT_CUSTOM_SETTINGS < /dev/null - - if [[ -n $FUEL_WEB_FETCH_REPO ]]; then - git fetch "$FUEL_WEB_FETCH_REPO" "$FUEL_WEB_FETCH_REFSPEC" || \ - { echo "Failed to fetch $FUEL_WEB_FETCH_REPO"; exit 1; } - fi - - git checkout "$FUEL_WEB_COMMIT" || \ - { echo "Failed to checkout to $FUEL_WEB_COMMIT"; exit 1; } - - popd > /dev/null - -} - -function cleanup_fuel_web_repo { - echo "Removing $FUEL_WEB_ROOT directory." - - if [[ "$FUEL_WEB_CLONE" == "yes" ]]; then - rm -rf $FUEL_WEB_ROOT - fi -} diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 98d3f596..00000000 --- a/tox.ini +++ /dev/null @@ -1,81 +0,0 @@ -[tox] -minversion = 2.1 -skipsdist = True -envlist = py27,pep8,functional,cleanup - -[base] -ARTS = {env:ARTS:test_run} - -[common] -changedir={toxinidir}/nailgun -setenv = - NAILGUN_DB={env:TEST_NAILGUN_DB:nailgun} - NAILGUN_DB_USER={env:NAILGUN_DB_USER:nailgun} - NAILGUN_DB_USERPW={env:NAILGUN_DB_USERPW:nailgun} - NAILGUN_DB_PREPARE={env:NAILGUN_DB_PREPARE:no} - - FUEL_WEB_CLONE={env:FUEL_WEB_CLONE:yes} - FUEL_WEB_REPO={env:FUEL_WEB_REPO:https://github.com/openstack/fuel-web.git} - FUEL_WEB_COMMIT={env:FUEL_COMMIT:master} - FUEL_WEB_ROOT={env:FUEL_WEB_ROOT:/tmp/fuel_web} - FUEL_WEB_FETCH_REPO={env:FUEL_WEB_FETCH_REPO:} - FUEL_WEB_FETCH_REFSPEC={env:FUEL_WEB_FETCH_REFSPEC:} - - NAILGUN_PORT={env:NAILGUN_PORT:8000} - NAILGUN_ROOT={env:FUEL_WEB_ROOT}/nailgun - FUELCLIENT_CUSTOM_SETTINGS={[base]ARTS}/fuelclient_custom_settings.yaml - -[testenv] -usedevelop = True -whitelist_externals = bash - python -setenv = VIRTUAL_ENV={envdir} - {[common]setenv} -passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -commands = - ostestr --serial {posargs} - -[testenv:functional] -setenv = VIRTUAL_ENV={envdir} - {[common]setenv} - OS_TEST_PATH={toxinidir}/fuelclient/tests/functional -commands = - bash -c "{toxinidir}/tools/env.sh prepare_fuel_web_repo" - bash -c "{toxinidir}/tools/env.sh prepare_nailgun" - bash -c "{toxinidir}/tools/env.sh prepare_fuelclient" - ostestr --serial {posargs} - -[testenv:cleanup] -commands = - bash -c "{toxinidir}/tools/env.sh cleanup_nailgun" - bash -c "{toxinidir}/tools/env.sh cleanup_fuel_web_repo" - bash -c "{toxinidir}/tools/env.sh cleanup_fuelclient" - bash -c "find {toxinidir} -name \"*.pyc\" -delete" - -[testenv:pep8] -commands = - flake8 {posargs:fuelclient} - -[testenv:cover] -commands = - python setup.py test --coverage --testr-args '{posargs}' - -[testenv:venv] -commands = {posargs:} - -[testenv:devenv] -envdir = devenv -usedevelop = True - -[flake8] -# TODO(atykhonov): H405 must be removed when old CLI is removed -ignore = H405 -exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,__init__.py,docs -show-pep8 = True -show-source = True -count = True - -[hacking] -import_exceptions = testtools.matchers