summaryrefslogtreecommitdiffstats
path: root/app/test
diff options
context:
space:
mode:
authorKoren Lev <korenlev@gmail.com>2017-07-27 15:04:07 +0000
committerGerrit Code Review <gerrit@opnfv.org>2017-07-27 15:04:07 +0000
commit162c03ef301396072c1934e7e7e0c40a841b4fe2 (patch)
tree7a2a2781949252436450ff5832962785061a774a /app/test
parentb88c78e3cf2bef22aa2f1c4d0bf305e303bc15f0 (diff)
parent7e83d0876ddb84a45e130eeba28bc40ef53c074b (diff)
Merge "Calipso initial release for OPNFV"
Diffstat (limited to 'app/test')
-rw-r--r--app/test/__init__.py10
-rw-r--r--app/test/api/__init__.py10
-rw-r--r--app/test/api/responders_test/__init__.py10
-rw-r--r--app/test/api/responders_test/auth/__init__.py10
-rw-r--r--app/test/api/responders_test/auth/test_tokens.py105
-rw-r--r--app/test/api/responders_test/resource/__init__.py10
-rw-r--r--app/test/api/responders_test/resource/test_aggregates.py103
-rw-r--r--app/test/api/responders_test/resource/test_clique_constraints.py138
-rw-r--r--app/test/api/responders_test/resource/test_clique_types.py267
-rw-r--r--app/test/api/responders_test/resource/test_cliques.py240
-rw-r--r--app/test/api/responders_test/resource/test_constants.py53
-rw-r--r--app/test/api/responders_test/resource/test_environment_configs.py420
-rw-r--r--app/test/api/responders_test/resource/test_inventory.py162
-rw-r--r--app/test/api/responders_test/resource/test_links.py193
-rw-r--r--app/test/api/responders_test/resource/test_messages.py236
-rw-r--r--app/test/api/responders_test/resource/test_monitoring_config_templates.py156
-rw-r--r--app/test/api/responders_test/resource/test_scans.py239
-rw-r--r--app/test/api/responders_test/resource/test_scheduled_scans.py247
-rw-r--r--app/test/api/responders_test/test_data/__init__.py10
-rw-r--r--app/test/api/responders_test/test_data/aggregates.py67
-rw-r--r--app/test/api/responders_test/test_data/base.py179
-rw-r--r--app/test/api/responders_test/test_data/clique_constraints.py74
-rw-r--r--app/test/api/responders_test/test_data/clique_types.py170
-rw-r--r--app/test/api/responders_test/test_data/cliques.py171
-rw-r--r--app/test/api/responders_test/test_data/constants.py23
-rw-r--r--app/test/api/responders_test/test_data/environment_configs.py221
-rw-r--r--app/test/api/responders_test/test_data/inventory.py37
-rw-r--r--app/test/api/responders_test/test_data/links.py90
-rw-r--r--app/test/api/responders_test/test_data/messages.py108
-rw-r--r--app/test/api/responders_test/test_data/monitoring_config_templates.py98
-rw-r--r--app/test/api/responders_test/test_data/scans.py187
-rw-r--r--app/test/api/responders_test/test_data/scheduled_scans.py138
-rw-r--r--app/test/api/responders_test/test_data/tokens.py83
-rw-r--r--app/test/api/test_base.py101
-rw-r--r--app/test/event_based_scan/__init__.py10
-rw-r--r--app/test/event_based_scan/config/__init__.py10
-rw-r--r--app/test/event_based_scan/config/test_config.py17
-rw-r--r--app/test/event_based_scan/test_data/__init__.py10
-rw-r--r--app/test/event_based_scan/test_data/event_payload_instance_add.py122
-rw-r--r--app/test/event_based_scan/test_data/event_payload_instance_delete.py97
-rw-r--r--app/test/event_based_scan/test_data/event_payload_instance_update.py99
-rw-r--r--app/test/event_based_scan/test_data/event_payload_interface_add.py350
-rw-r--r--app/test/event_based_scan/test_data/event_payload_interface_delete.py350
-rw-r--r--app/test/event_based_scan/test_data/event_payload_network_add.py32
-rw-r--r--app/test/event_based_scan/test_data/event_payload_network_delete.py88
-rw-r--r--app/test/event_based_scan/test_data/event_payload_network_update.py65
-rw-r--r--app/test/event_based_scan/test_data/event_payload_port_add.py314
-rw-r--r--app/test/event_based_scan/test_data/event_payload_port_delete.py290
-rw-r--r--app/test/event_based_scan/test_data/event_payload_port_update.py103
-rw-r--r--app/test/event_based_scan/test_data/event_payload_router_add.py176
-rw-r--r--app/test/event_based_scan/test_data/event_payload_router_delete.py59
-rw-r--r--app/test/event_based_scan/test_data/event_payload_router_update.py271
-rw-r--r--app/test/event_based_scan/test_data/event_payload_subnet_add.py124
-rw-r--r--app/test/event_based_scan/test_data/event_payload_subnet_delete.py95
-rw-r--r--app/test/event_based_scan/test_data/event_payload_subnet_update.py76
-rw-r--r--app/test/event_based_scan/test_event.py55
-rw-r--r--app/test/event_based_scan/test_event_delete_base.py64
-rw-r--r--app/test/event_based_scan/test_instance_add.py61
-rw-r--r--app/test/event_based_scan/test_instance_delete.py24
-rw-r--r--app/test/event_based_scan/test_instance_update.py46
-rw-r--r--app/test/event_based_scan/test_interface_add.py74
-rw-r--r--app/test/event_based_scan/test_interface_delete.py44
-rw-r--r--app/test/event_based_scan/test_network_add.py47
-rw-r--r--app/test/event_based_scan/test_network_delete.py24
-rw-r--r--app/test/event_based_scan/test_network_update.py33
-rw-r--r--app/test/event_based_scan/test_port_add.py75
-rw-r--r--app/test/event_based_scan/test_port_delete.py47
-rw-r--r--app/test/event_based_scan/test_port_update.py34
-rw-r--r--app/test/event_based_scan/test_router_add.py79
-rw-r--r--app/test/event_based_scan/test_router_delete.py23
-rw-r--r--app/test/event_based_scan/test_router_update.py62
-rw-r--r--app/test/event_based_scan/test_subnet_add.py68
-rw-r--r--app/test/event_based_scan/test_subnet_delete.py54
-rw-r--r--app/test/event_based_scan/test_subnet_update.py45
-rw-r--r--app/test/fetch/__init__.py9
-rw-r--r--app/test/fetch/api_fetch/__init__.py9
-rw-r--r--app/test/fetch/api_fetch/test_api_access.py142
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_availability_zone.py72
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_host_instances.py83
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_networks.py65
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_ports.py89
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_project_hosts.py137
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_projects.py120
-rw-r--r--app/test/fetch/api_fetch/test_api_fetch_regions.py41
-rw-r--r--app/test/fetch/api_fetch/test_data/__init__.py9
-rw-r--r--app/test/fetch/api_fetch/test_data/api_access.py55
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_availability_zones.py71
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_host_instances.py85
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_host_project_hosts.py225
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_networks.py72
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_ports.py72
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_projects.py88
-rw-r--r--app/test/fetch/api_fetch/test_data/api_fetch_regions.py50
-rw-r--r--app/test/fetch/api_fetch/test_data/configurations.py52
-rw-r--r--app/test/fetch/api_fetch/test_data/regions.py110
-rw-r--r--app/test/fetch/api_fetch/test_data/token.py23
-rw-r--r--app/test/fetch/cli_fetch/__init__.py9
-rw-r--r--app/test/fetch/cli_fetch/test_cli_access.py159
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_host_pnics.py135
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_host_pnics_vpp.py34
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_host_vservices.py132
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics.py111
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_ovs.py36
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_vpp.py23
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_vconnectors.py66
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_ovs.py38
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_vpp.py50
-rw-r--r--app/test/fetch/cli_fetch/test_cli_fetch_vservice_vnics.py124
-rw-r--r--app/test/fetch/cli_fetch/test_data/__init__.py9
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_access.py58
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics.py147
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics_vpp.py204
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_host_verservices.py276
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_instance_vnics.py288
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors.py103
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_ovs.py234
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_vpp.py137
-rw-r--r--app/test/fetch/cli_fetch/test_data/cli_fetch_vservice_vnics.py616
-rw-r--r--app/test/fetch/config/__init__.py9
-rw-r--r--app/test/fetch/config/test_config.py17
-rw-r--r--app/test/fetch/db_fetch/__init__.py9
-rw-r--r--app/test/fetch/db_fetch/mock_cursor.py25
-rw-r--r--app/test/fetch/db_fetch/test_data/__init__.py9
-rw-r--r--app/test/fetch/db_fetch/test_data/db_access.py40
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_aggregate_hosts.py34
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_aggregates.py17
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_host_network_agents.py65
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_instances.py91
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_oteps.py131
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_vedges_ovs.py168
-rw-r--r--app/test/fetch/db_fetch/test_data/db_fetch_vedges_vpp.py89
-rw-r--r--app/test/fetch/db_fetch/test_db_access.py108
-rw-r--r--app/test/fetch/db_fetch/test_db_fetch_aggregate_hosts.py60
-rw-r--r--app/test/fetch/db_fetch/test_db_fetch_aggregates.py26
-rw-r--r--app/test/fetch/db_fetch/test_db_fetch_instances.py37
-rw-r--r--app/test/fetch/db_fetch/test_db_fetch_oteps.py92
-rw-r--r--app/test/fetch/db_fetch/test_db_fetch_vedges_ovs.py109
-rw-r--r--app/test/fetch/db_fetch/test_db_fetch_vedges_vpp.py82
-rw-r--r--app/test/fetch/db_fetch/test_fetch_host_network_agents.py66
-rw-r--r--app/test/fetch/test_fetch.py46
-rw-r--r--app/test/scan/__init__.py10
-rw-r--r--app/test/scan/config/__init__.py9
-rw-r--r--app/test/scan/config/test_config.py17
-rw-r--r--app/test/scan/main.py17
-rw-r--r--app/test/scan/mock_module.py37
-rw-r--r--app/test/scan/test_data/__init__.py9
-rw-r--r--app/test/scan/test_data/configurations.py69
-rw-r--r--app/test/scan/test_data/metadata.py318
-rw-r--r--app/test/scan/test_data/scan.py435
-rw-r--r--app/test/scan/test_data/scanner.py355
-rw-r--r--app/test/scan/test_scan.py46
-rw-r--r--app/test/scan/test_scan_controller.py215
-rw-r--r--app/test/scan/test_scan_metadata_parser.py152
-rw-r--r--app/test/scan/test_scanner.py355
-rw-r--r--app/test/test_suite.py25
155 files changed, 16150 insertions, 0 deletions
diff --git a/app/test/__init__.py b/app/test/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/api/__init__.py b/app/test/api/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/api/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/api/responders_test/__init__.py b/app/test/api/responders_test/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/api/responders_test/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/api/responders_test/auth/__init__.py b/app/test/api/responders_test/auth/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/api/responders_test/auth/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/api/responders_test/auth/test_tokens.py b/app/test/api/responders_test/auth/test_tokens.py
new file mode 100644
index 0000000..d7b9675
--- /dev/null
+++ b/app/test/api/responders_test/auth/test_tokens.py
@@ -0,0 +1,105 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import json
+from unittest.mock import patch
+
+from test.api.responders_test.test_data import base
+
+from test.api.responders_test.test_data import tokens
+from test.api.test_base import TestBase
+
+
+class TestTokens(TestBase):
+
+ def test_create_token_without_auth_obj(self):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITHOUT_AUTH),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_create_token_without_methods(self):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITHOUT_METHODS),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_create_token_without_credentials_in_credentials_method(self):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITHOUT_CREDENTIALS),
+ expected_code=base.UNAUTHORIZED_CODE)
+
+ def test_create_token_without_token_in_token_method(self):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITHOUT_TOKEN),
+ expected_code=base.UNAUTHORIZED_CODE)
+
+ @patch(tokens.AUTH_VALIDATE_CREDENTIALS)
+ def test_create_token_with_wrong_credentials(self, validate_credentials):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITH_WRONG_CREDENTIALS),
+ mocks={
+ validate_credentials: False
+ },
+ expected_code=base.UNAUTHORIZED_CODE)
+
+ @patch(tokens.AUTH_VALIDATE_TOKEN)
+ def test_create_token_with_wrong_token(self, validate_token):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITH_WRONG_TOKEN),
+ mocks={
+ validate_token: 'token error'
+ },
+ expected_code=base.UNAUTHORIZED_CODE)
+
+ @patch(tokens.AUTH_WRITE_TOKEN)
+ @patch(tokens.AUTH_VALIDATE_CREDENTIALS)
+ def test_create_token_with_correct_credentials(self, validate_credentials, write_token):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITH_CORRECT_CREDENTIALS),
+ mocks={
+ validate_credentials: True,
+ write_token: None
+ },
+ expected_code=base.CREATED_CODE)
+
+ @patch(tokens.AUTH_WRITE_TOKEN)
+ @patch(tokens.AUTH_VALIDATE_TOKEN)
+ def test_create_token_with_correct_token(self, validate_token, write_token):
+ self.validate_post_request(tokens.URL,
+ body=json.dumps(tokens.AUTH_OBJ_WITH_CORRECT_TOKEN),
+ mocks={
+ validate_token: None,
+ write_token: None
+ },
+ expected_code=base.CREATED_CODE)
+
+ def test_delete_token_without_token(self):
+ self.validate_delete_request(tokens.URL,
+ headers=tokens.HEADER_WITHOUT_TOKEN,
+ expected_code=base.UNAUTHORIZED_CODE
+ )
+
+ @patch(tokens.AUTH_VALIDATE_TOKEN)
+ def test_delete_token_with_wrong_token(self, validate_token):
+ self.validate_delete_request(tokens.URL,
+ headers=tokens.HEADER_WITH_WRONG_TOKEN,
+ mocks={
+ validate_token: 'token error'
+ },
+ expected_code=base.UNAUTHORIZED_CODE)
+
+ @patch(tokens.AUTH_VALIDATE_TOKEN)
+ @patch(tokens.AUTH_DELETE_TOKEN)
+ def test_delete_token_with_correct_token(self, delete_token, validate_token):
+ self.validate_delete_request(tokens.URL,
+ headers=tokens.HEADER_WITH_CORRECT_TOKEN,
+ mocks={
+ validate_token: None,
+ delete_token: None
+ },
+ expected_code=base.SUCCESSFUL_CODE)
diff --git a/app/test/api/responders_test/resource/__init__.py b/app/test/api/responders_test/resource/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/api/responders_test/resource/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/api/responders_test/resource/test_aggregates.py b/app/test/api/responders_test/resource/test_aggregates.py
new file mode 100644
index 0000000..1b642e0
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_aggregates.py
@@ -0,0 +1,103 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import aggregates
+from unittest.mock import patch
+
+
+class TestAggregates(TestBase):
+
+ def test_get_aggregate_without_type(self):
+ self.validate_get_request(aggregates.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_aggregate_with_wrong_filter(self):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "unknown": "unknown"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_environment_aggregates_without_env_name(self):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "type": aggregates.ENV_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_get_environment_aggregates_with_unknown_env_name(self,
+ check_env_name):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "type": aggregates.ENV_TYPE,
+ "env_name": base.UNKNOWN_ENV
+ },
+ mocks={
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_AGGREGATE)
+ def test_get_environment_aggregates_with_env_name(self, aggregates_method,
+ check_env_name):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "type": aggregates.ENV_TYPE,
+ "env_name": base.ENV_NAME
+ },
+ mocks={
+ check_env_name: True,
+ aggregates_method:
+ aggregates.ENVIRONMENT_AGGREGATES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=
+ aggregates.ENVIRONMENT_AGGREGATES_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_AGGREGATE)
+ def test_get_message_aggregates(self, aggregate):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "type": aggregates.MESSAGE_TYPE
+ },
+ side_effects={aggregate: [
+ aggregates.MESSAGE_ENV_AGGREGATES,
+ aggregates.MESSAGE_LEVEL_AGGREGATES]
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=
+ aggregates.MESSAGE_AGGREGATES_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_AGGREGATE)
+ def test_get_constant_aggregates(self, aggregate):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "type": aggregates.CONSTANT_TYPE
+ },
+ mocks={
+ aggregate: aggregates.CONSTANT_AGGREGATES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=
+ aggregates.CONSTANT_AGGREGATES_RESPONSE
+ )
+
+ def test_get_unknown_aggregates(self):
+ self.validate_get_request(aggregates.URL,
+ params={
+ "type": aggregates.UNKNOWN_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
diff --git a/app/test/api/responders_test/resource/test_clique_constraints.py b/app/test/api/responders_test/resource/test_clique_constraints.py
new file mode 100644
index 0000000..f990b5c
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_clique_constraints.py
@@ -0,0 +1,138 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import clique_constraints
+from unittest.mock import patch
+
+
+class TestCliqueConstraints(TestBase):
+
+ def test_get_clique_constraints_list_with_invalid_filter(self):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "invalid": "invalid"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_clique_constraints_list_with_non_int_page(self):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_constraints_list_with_int_page(self, read):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: clique_constraints.CLIQUE_CONSTRAINTS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_constraints.
+ CLIQUE_CONSTRAINTS_RESPONSE
+ )
+
+ def test_get_clique_constraints_list_with_non_int_pagesize(self):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_constraints_list_with_int_pagesize(self, read):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: clique_constraints.CLIQUE_CONSTRAINTS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_constraints.
+ CLIQUE_CONSTRAINTS_RESPONSE
+ )
+
+ def test_get_clique_constraints_with_wrong_id(self):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ 'id': clique_constraints.WRONG_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_constraints_with_nonexistent_id(self, read):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "id": clique_constraints.NONEXISTENT_ID
+ },
+ mocks={
+ read: []
+ },
+ expected_code=base.NOT_FOUND_CODE
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_constraints_with_id(self, read):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "id": clique_constraints.CORRECT_ID
+ },
+ mocks={
+ read: clique_constraints.
+ CLIQUE_CONSTRAINTS_WITH_SPECIFIC_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_constraints.
+ CLIQUE_CONSTRAINTS_WITH_SPECIFIC_ID[0]
+ )
+
+ def test_get_clique_constraints_list_with_wrong_focal_point_type(self):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "focal_point_type":
+ clique_constraints.WRONG_FOCAL_POINT_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_constraints_list_with_focal_point_type(self, read):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "focal_point_type":
+ clique_constraints.CORRECT_FOCAL_POINT_TYPE
+ },
+ mocks={
+ read: clique_constraints.
+ CLIQUE_CONSTRAINTS_WITH_SPECIFIC_FOCAL_POINT_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_constraints.
+ CLIQUE_CONSTRAINTS_WITH_SPECIFIC_FOCAL_POINT_TYPE_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_constraints_list_with_constraints(self, read):
+ self.validate_get_request(clique_constraints.URL,
+ params={
+ "constraint": clique_constraints.CONSTRAINT
+ },
+ mocks={
+ read: clique_constraints.
+ CLIQUE_CONSTRAINTS_WITH_SPECIFIC_CONSTRAINT
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_constraints.
+ CLIQUE_CONSTRAINTS_WITH_SPECIFIC_CONSTRAINT_RESPONSE
+ )
diff --git a/app/test/api/responders_test/resource/test_clique_types.py b/app/test/api/responders_test/resource/test_clique_types.py
new file mode 100644
index 0000000..f5e331e
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_clique_types.py
@@ -0,0 +1,267 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import json
+
+from test.api.responders_test.test_data import base
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import clique_types
+from unittest.mock import patch
+
+
+class TestCliqueTypes(TestBase):
+
+ def test_get_clique_types_list_without_env_name(self):
+ self.validate_get_request(clique_types.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_clique_types_with_invalid_filter(self):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "invalid": "invalid"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_clique_type_with_wrong_id(self):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": clique_types.WRONG_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_type_with_id(self, read):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": clique_types.CORRECT_ID
+ },
+ mocks={
+ read: clique_types.CLIQUE_TYPES_WITH_SPECIFIC_ID
+ },
+ expected_response=clique_types.
+ CLIQUE_TYPES_WITH_SPECIFIC_ID[0],
+ expected_code=base.SUCCESSFUL_CODE
+ )
+
+ def test_get_clique_types_list_with_wrong_focal_point_type(self):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "focal_point_type": clique_types.WRONG_FOCAL_POINT_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_types_list_with_correct_focal_point_type(self, read):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "focal_point_type":
+ clique_types.CORRECT_FOCAL_POINT_POINT_TYPE
+ },
+ mocks={
+ read: clique_types.
+ CLIQUE_TYPES_WITH_SPECIFIC_FOCAL_POINT_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_types.
+ CLIQUE_TYPES_WITH_SPECIFIC_FOCAL_POINT_TYPE_RESPONSE
+ )
+
+ def test_get_clique_types_list_with_wrong_link_type(self):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_type": clique_types.WRONG_LINK_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_types_list_with_correct_link_type(self, read):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_type": base.CORRECT_LINK_TYPE
+ },
+ mocks={
+ read: clique_types.
+ CLIQUE_TYPES_WITH_SPECIFIC_LINK_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_types.
+ CLIQUE_TYPES_WITH_SPECIFIC_LINK_TYPE_RESPONSE
+ )
+
+ def test_get_clique_types_list_with_non_int_page(self):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_types_list_with_int_page(self, read):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: clique_types.CLIQUE_TYPES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_types.CLIQUE_TYPES_RESPONSE)
+
+ def test_get_clique_types_list_with_non_int_page_size(self):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_types_list_with_int_page_size(self, read):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: clique_types.CLIQUE_TYPES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=clique_types.CLIQUE_TYPES_RESPONSE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_types_list_with_unknown_env_name(self, read, check_env_name):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.UNKNOWN_ENV
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_types_list_with_env_name_and_nonexistent_link_type(self, read, check_env_name):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_type": clique_types.NONEXISTENT_LINK_TYPE
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_type_with_unknown_env_name_and_id(self, read, check_env_name):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.UNKNOWN_ENV,
+ "id": clique_types.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_type_with_env_name_and_nonexistent_id(self, read, check_env_name):
+ self.validate_get_request(clique_types.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": clique_types.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ def test_post_clique_type_with_non_dict_clique_type(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.NON_DICT_CLIQUE_TYPE),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_without_env_name(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.CLIQUE_TYPE_WITHOUT_ENVIRONMENT),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_post_clique_type_with_unknown_env_name(self, check_environment_name):
+ self.validate_post_request(clique_types.URL,
+ mocks={
+ check_environment_name: False
+ },
+ body=json.dumps(clique_types.
+ CLIQUE_TYPE_WITH_UNKNOWN_ENVIRONMENT),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_without_focal_point_type(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.
+ CLIQUE_TYPE_WITHOUT_FOCAL_POINT_TYPE),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_with_wrong_focal_point_type(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.
+ CLIQUE_TYPE_WITH_WRONG_FOCAL_POINT_TYPE),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_without_link_types(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(
+ clique_types.CLIQUE_TYPE_WITHOUT_LINK_TYPES
+ ),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_with_non_list_link_types(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.
+ CLIQUE_TYPE_WITH_NON_LIST_LINK_TYPES),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_with_wrong_link_type(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.
+ CLIQUE_TYPE_WITH_WRONG_LINK_TYPE),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_clique_type_without_name(self):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.CLIQUE_TYPE_WITHOUT_NAME),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_WRITE)
+ def test_post_clique_type(self, write, check_environment_name):
+ self.validate_post_request(clique_types.URL,
+ body=json.dumps(clique_types.CLIQUE_TYPE),
+ mocks={
+ write: None,
+ check_environment_name: True
+ },
+ expected_code=base.CREATED_CODE)
diff --git a/app/test/api/responders_test/resource/test_cliques.py b/app/test/api/responders_test/resource/test_cliques.py
new file mode 100644
index 0000000..de3576b
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_cliques.py
@@ -0,0 +1,240 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import cliques
+from unittest.mock import patch
+
+
+class TestCliques(TestBase):
+
+ def test_get_cliques_list_without_env_name(self):
+ self.validate_get_request(cliques.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_cliques_list_with_invalid_filter(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "invalid": "invalid"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_cliques_list_with_non_int_page(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_int_page(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: cliques.CLIQUES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.CLIQUES_RESPONSE)
+
+ def test_get_cliques_list_with_non_int_pagesize(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_int_pagesize(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: cliques.CLIQUES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.CLIQUES_RESPONSE)
+
+ def test_get_clique_with_wrong_clique_id(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': cliques.WRONG_CLIQUE_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_with_clique_id(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": cliques.CORRECT_CLIQUE_ID
+ },
+ mocks={
+ read: cliques.CLIQUES_WITH_SPECIFIC_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.CLIQUES_WITH_SPECIFIC_ID[0]
+ )
+
+ def test_get_cliques_list_with_wrong_focal_point(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "focal_point": cliques.WRONG_FOCAL_POINT
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_focal_point(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "focal_point": cliques.CORRECT_FOCAL_POINT
+ },
+ mocks={
+ read: cliques.CLIQUES_WITH_SPECIFIC_FOCAL_POINT
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.
+ CLIQUES_WITH_SPECIFIC_FOCAL_POINT_RESPONSE
+ )
+
+ def test_get_cliques_list_with_wrong_focal_point_type(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "focal_point_type": cliques.WRONG_FOCAL_POINT_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_focal_point_type(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "focal_point_type": cliques.CORRECT_FOCAL_POINT_TYPE
+ },
+ mocks={
+ read: cliques.CLIQUES_WITH_SPECIFIC_FOCAL_POINT_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.
+ CLIQUES_WITH_SPECIFIC_FOCAL_POINT_TYPE_RESPONSE
+ )
+
+ def test_get_cliques_list_with_wrong_link_type(self):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_type": base.WRONG_LINK_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_link_type(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_type": cliques.CORRECT_LINK_TYPE
+ },
+ mocks={
+ read: cliques.CLIQUES_WITH_SPECIFIC_LINK_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.
+ CLIQUES_WITH_SPECIFIC_LINK_TYPE_RESPONSE
+ )
+
+ def test_get_cliques_list_with_wrong_link_id(self):
+ self.validate_get_request(cliques.URL,
+ {
+ "env_name": base.ENV_NAME,
+ "link_id": cliques.WRONG_LINK_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_ids_with_correct_link_id(self, read):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_id": cliques.CORRECT_LINK_ID
+ },
+ mocks={
+ read: cliques.CLIQUES_WITH_SPECIFIC_LINK_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=cliques.
+ CLIQUES_WITH_SPECIFIC_LINK_ID_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_env_name_and_nonexistent_link_id(self, read, check_env_name):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "link_id": cliques.NONEXISTENT_LINK_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_cliques_list_with_unknown_env_name(self, read, check_env_name):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.UNKNOWN_ENV
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_with_env_name_and_nonexistent_clique_id(self, read, check_env_name):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": cliques.NONEXISTENT_CLIQUE_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_clique_with_unknown_env_name_and_clique_id(self, read, check_env_name):
+ self.validate_get_request(cliques.URL,
+ params={
+ "env_name": base.UNKNOWN_ENV,
+ "id": cliques.NONEXISTENT_CLIQUE_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
diff --git a/app/test/api/responders_test/resource/test_constants.py b/app/test/api/responders_test/resource/test_constants.py
new file mode 100644
index 0000000..0d92ebe
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_constants.py
@@ -0,0 +1,53 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import constants
+from unittest.mock import patch
+
+
+class TestConstants(TestBase):
+
+ def test_get_constant_without_name(self):
+ self.validate_get_request(constants.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_constant_with_unknown_filter(self):
+ self.validate_get_request(constants.URL,
+ params={
+ "unknown": "unknown"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_constant_with_unknown_name(self, read):
+ self.validate_get_request(constants.URL,
+ params={
+ "name": constants.UNKNOWN_NAME
+ },
+ mocks={
+ read: []
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_constant(self, read):
+ self.validate_get_request(constants.URL,
+ params={
+ "name": constants.NAME
+ },
+ mocks={
+ read: constants.CONSTANTS_WITH_SPECIFIC_NAME
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=constants.
+ CONSTANTS_WITH_SPECIFIC_NAME[0]
+ )
diff --git a/app/test/api/responders_test/resource/test_environment_configs.py b/app/test/api/responders_test/resource/test_environment_configs.py
new file mode 100644
index 0000000..7002ed7
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_environment_configs.py
@@ -0,0 +1,420 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import json
+
+from test.api.responders_test.test_data import base
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import environment_configs
+from utils.constants import EnvironmentFeatures
+from utils.inventory_mgr import InventoryMgr
+from unittest.mock import patch
+
+
+class TestEnvironmentConfigs(TestBase):
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={},
+ mocks={
+ read: environment_configs.ENV_CONFIGS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_invalid_filters(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "unknown": "unknown"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_name(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "name": environment_configs.NAME
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_NAME
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_NAME[0]
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_unknown_name(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "name": environment_configs.UNKNOWN_NAME
+ },
+ mocks={
+ read: []
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ def test_get_environment_configs_list_with_wrong_distribution(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "distribution":
+ environment_configs.WRONG_DISTRIBUTION
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_distribution(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "distribution":
+ environment_configs.CORRECT_DISTRIBUTION
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_DISTRIBUTION
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_DISTRIBUTION_RESPONSE)
+
+ def test_get_environment_configs_list_with_wrong_mechanism_driver(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "mechanism_drivers":
+ environment_configs.WRONG_MECHANISM_DRIVER
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_mechanism_driver(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "mechanism_drivers":
+ environment_configs.CORRECT_MECHANISM_DRIVER
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_MECHANISM_DRIVER
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_MECHANISM_DRIVER_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_wrong_type_driver(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "type_drivers":
+ environment_configs.WRONG_TYPE_DRIVER
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_type_driver(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "type_drivers":
+ environment_configs.CORRECT_TYPE_DRIVER
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_TYPE_DRIVER
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_TYPE_DRIVER_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_user(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "user": environment_configs.USER
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_USER
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_USER_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_non_bool_listen(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "listen": environment_configs.NON_BOOL_LISTEN
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_bool_listen(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "listen": environment_configs.BOOL_LISTEN
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_LISTEN
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_LISTEN_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_non_bool_scanned(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "scanned": environment_configs.
+ NON_BOOL_SCANNED
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_bool_scanned(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "scanned": environment_configs.BOOL_SCANNED
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_SCANNED
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_SCANNED_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_non_bool_monitoring_setup_done(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "listen": environment_configs.
+ NON_BOOL_MONITORING_SETUP_DONE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_bool_monitoring_setup_done(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "scanned": environment_configs.
+ BOOL_MONITORING_SETUP_DONE
+ },
+ mocks={
+ read: environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_MONITORING_SETUP_DONE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_WITH_SPECIFIC_MONITORING_SETUP_DONE_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_non_int_page(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_int_page(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: environment_configs.ENV_CONFIGS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_RESPONSE
+ )
+
+ def test_get_environment_configs_list_with_non_int_page_size(self):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_environment_configs_list_with_int_page_size(self, read):
+ self.validate_get_request(environment_configs.URL,
+ params={
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: environment_configs.ENV_CONFIGS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=environment_configs.
+ ENV_CONFIGS_RESPONSE
+ )
+
+ def test_post_environment_config_without_app_path(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["app_path"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_configuration(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["configuration"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_distribution(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["distribution"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_with_wrong_distribution(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ updates={"distribution": environment_configs.WRONG_DISTRIBUTION})
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_listen(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["listen"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_with_wrong_listen(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ updates={"listen": environment_configs.NON_BOOL_LISTEN})
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_mechanism_driver(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["mechanism_drivers"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_with_wrong_mechanism_driver(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ updates={
+ "mechanism_drivers":
+ [environment_configs.WRONG_MECHANISM_DRIVER]
+ })
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_name(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["name"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_operational(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["operational"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_with_wrong_scanned(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ updates={
+ "scanned": environment_configs.NON_BOOL_SCANNED
+ })
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_with_wrong_last_scanned(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ updates={
+ "last_scanned": base.WRONG_FORMAT_TIME
+ })
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_type(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["type"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_without_type_drivers(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ deleted_keys=["type_drivers"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_environment_config_with_wrong_type_drivers(self):
+ test_data = self.get_updated_data(environment_configs.ENV_CONFIG,
+ updates={
+ "type_drivers": [environment_configs.WRONG_TYPE_DRIVER]
+ })
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(test_data),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def mock_validate_env_config_with_supported_envs(self, scanning,
+ monitoring, listening):
+ InventoryMgr.is_feature_supported_in_env = lambda self, matches, feature: {
+ EnvironmentFeatures.SCANNING: scanning,
+ EnvironmentFeatures.MONITORING: monitoring,
+ EnvironmentFeatures.LISTENING: listening
+ }[feature]
+
+ @patch(base.RESPONDER_BASE_WRITE)
+ def test_post_environment_config(self, write):
+ self.mock_validate_env_config_with_supported_envs(True, True, True)
+ self.validate_post_request(environment_configs.URL,
+ mocks={
+ write: None
+ },
+ body=json.dumps(environment_configs.ENV_CONFIG),
+ expected_code=base.CREATED_CODE)
+
+ def test_post_unsupported_environment_config(self):
+ test_cases = [
+ {
+ "scanning": False,
+ "monitoring": True,
+ "listening": True
+ },
+ {
+ "scanning": True,
+ "monitoring": False,
+ "listening": True
+ },
+ {
+ "scanning": True,
+ "monitoring": True,
+ "listening": False
+ }
+ ]
+ for test_case in test_cases:
+ self.mock_validate_env_config_with_supported_envs(test_case["scanning"],
+ test_case["monitoring"],
+ test_case["listening"])
+ self.validate_post_request(environment_configs.URL,
+ body=json.dumps(environment_configs.ENV_CONFIG),
+ expected_code=base.BAD_REQUEST_CODE)
diff --git a/app/test/api/responders_test/resource/test_inventory.py b/app/test/api/responders_test/resource/test_inventory.py
new file mode 100644
index 0000000..0ef9089
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_inventory.py
@@ -0,0 +1,162 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import inventory
+from test.api.test_base import TestBase
+from unittest.mock import patch
+
+
+class TestInventory(TestBase):
+
+ def test_get_objects_list_without_env_name(self):
+ self.validate_get_request(inventory.URL,
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_objects_list_with_invalid_filter(self):
+ self.validate_get_request(inventory.URL,
+ params={
+ "invalid": "invalid"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_objects_list_with_non_boolean_subtree(self):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'sub_tree': base.NON_BOOL
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_objects_list_with_boolean_subtree(self, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'sub_tree': base.BOOL
+ },
+ mocks={
+ read: inventory.OBJECTS_LIST
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=inventory.OBJECT_IDS_RESPONSE
+ )
+
+ def test_get_objects_list_with_non_int_page(self):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page': base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_objects_list_with_int_page(self, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page': base.INT_PAGE
+ },
+ mocks={
+ read: inventory.OBJECTS_LIST
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=inventory.OBJECT_IDS_RESPONSE
+ )
+
+ def test_get_objects_list_with_non_int_pagesize(self):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page_size': base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_objects_list_with_int_pagesize(self, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page_size': base.INT_PAGESIZE
+ },
+ mocks={
+ read: inventory.OBJECTS_LIST
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=inventory.OBJECT_IDS_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_get_nonexistent_objects_list_with_env_name(self, check_env_name, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE,
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_get_objects_list_with_unkown_env_name(self, check_env_name, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_object_with_env_name_and_id(self, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': inventory.ID
+ },
+ mocks={
+ read: inventory.OBJECTS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=inventory.OBJECTS[0]
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_get_nonexistent_object_with_env_name_and_id(self, check_env_name, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': inventory.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_get_object_with_unkown_env_name_and_id(self, check_env_name, read):
+ self.validate_get_request(inventory.URL,
+ params={
+ 'env_name': base.UNKNOWN_ENV,
+ 'id': inventory.ID
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
diff --git a/app/test/api/responders_test/resource/test_links.py b/app/test/api/responders_test/resource/test_links.py
new file mode 100644
index 0000000..b312aa1
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_links.py
@@ -0,0 +1,193 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import links
+from test.api.test_base import TestBase
+from unittest.mock import patch
+
+
+class TestLinks(TestBase):
+
+ def test_get_links_list_without_env_name(self):
+ self.validate_get_request(links.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_links_list_with_invalid_filters(self):
+ self.validate_get_request(links.URL,
+ params={
+ 'invalid': 'invalid'
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_links_list_with_wrong_link_type(self):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'link_type': links.WRONG_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_links_list_with_correct_link_type(self, read):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'link_type': links.CORRECT_TYPE
+ },
+ mocks={
+ read: links.LINKS_WITH_SPECIFIC_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=links.
+ LINKS_WITH_SPECIFIC_TYPE_RESPONSE
+ )
+
+ def test_get_links_list_with_wrong_state(self):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'state': links.WRONG_STATE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_links_list_with_correct_state(self, read):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'state': links.CORRECT_STATE
+ },
+ mocks={
+ read: links.LINKS_WITH_SPECIFIC_STATE,
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=links.
+ LINKS_WITH_SPECIFIC_STATE_RESPONSE
+ )
+
+ def test_get_link_with_env_name_and_wrong_link_id(self):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': links.WRONG_LINK_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_link_with_env_name_and_link_id(self, read):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': links.LINK_ID
+ },
+ mocks={
+ read: links.LINKS_WITH_SPECIFIC_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=links.
+ LINKS_WITH_SPECIFIC_ID[0]
+ )
+
+ def test_get_links_list_with_non_int_page(self):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page': base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_links_list_with_int_page(self, read):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page': base.INT_PAGE
+ },
+ mocks={
+ read: links.LINKS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=links.LINKS_LIST_RESPONSE)
+
+ def test_get_link_ids_with_non_int_page_size(self):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page_size': base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_links_list_with_int_page_size(self, read):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page_size': base.INT_PAGESIZE
+ },
+ mocks={
+ read: links.LINKS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=links.LINKS_LIST_RESPONSE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_links_list_with_env_name_and_unknown_host(self, read, check_env_name):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'host': links.UNKNOWN_HOST
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_links_list_with_unknown_env_name(self, read, check_env_name):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.UNKNOWN_ENV
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_link_with_env_name_and_nonexistent_link_id(self, read, check_env_name):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': links.NONEXISTENT_LINK_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_link_with_unknown_env_name(self, read, check_env_name):
+ self.validate_get_request(links.URL,
+ params={
+ 'env_name': base.UNKNOWN_ENV
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
diff --git a/app/test/api/responders_test/resource/test_messages.py b/app/test/api/responders_test/resource/test_messages.py
new file mode 100644
index 0000000..6999cee
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_messages.py
@@ -0,0 +1,236 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import messages
+from unittest.mock import patch
+
+
+class TestMessage(TestBase):
+
+ def test_get_messages_list_without_env_name(self):
+ self.validate_get_request(messages.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_messages_list_with_invalid_filter(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'invalid': 'invalid'
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_messages_list_with_wrong_format_start_time(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'start_time': messages.WRONG_FORMAT_TIME
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_correct_format_start_time(self, read):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'start_time': messages.CORRECT_FORMAT_TIME
+ },
+ mocks={
+ read: messages.MESSAGES_WITH_SPECIFIC_TIME
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=
+ messages.MESSAGES_WITH_SPECIFIC_TIME_RESPONSE
+ )
+
+ def test_get_messages_list_with_wrong_format_end_time(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'end_time': messages.WRONG_FORMAT_TIME
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_correct_format_end_time(self, read):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'end_time': messages.CORRECT_FORMAT_TIME
+ },
+ mocks={
+ read: messages.MESSAGES_WITH_SPECIFIC_TIME
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=
+ messages.MESSAGES_WITH_SPECIFIC_TIME_RESPONSE
+ )
+
+ def test_get_messages_list_with_wrong_level(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'level': messages.WRONG_SEVERITY
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_level(self, read):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'level': messages.CORRECT_SEVERITY
+ },
+ mocks={
+ read: messages.MESSAGES_WITH_SPECIFIC_SEVERITY
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=messages.
+ MESSAGES_WITH_SPECIFIC_SEVERITY_RESPONSE
+ )
+
+ def test_get_messages_list_with_wrong_related_object_type(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'related_object_type':
+ messages.WRONG_RELATED_OBJECT_TYPE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_correct_related_object_type(self, read):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'related_object_type':
+ messages.CORRECT_RELATED_OBJECT_TYPE
+ },
+ mocks={
+ read: messages.
+ MESSAGES_WITH_SPECIFIC_RELATED_OBJECT_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=messages.
+ MESSAGES_WITH_SPECIFIC_RELATED_OBJECT_TYPE_RESPONSE
+ )
+
+ def test_get_messages_list_with_non_int_page(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page': base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_int_page(self, read):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page': base.INT_PAGE
+ },
+ mocks={
+ read: messages.MESSAGES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=messages.MESSAGES_RESPONSE)
+
+ def test_get_messages_list_with_non_int_page_size(self):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page_size': base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_int_pagesize(self, read):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'page_size': base.INT_PAGESIZE
+ },
+ mocks={
+ read: messages.MESSAGES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=messages.MESSAGES_RESPONSE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_env_name_and_nonexistent_related_object(self, read, check_env_name):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'related_object': messages.NONEXISTENT_RELATED_OBJECT
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_messages_list_with_unknown_env_name(self, read, check_env_name):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.UNKNOWN_ENV,
+ 'related_object': messages.RELATED_OBJECT
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_message_with_env_name_and_nonexistent_id(self, read, check_env_name):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': messages.NONEXISTENT_MESSAGE_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_message_with_unknown_env_name_and_id(self, read, check_env_name):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.UNKNOWN_ENV,
+ 'id': messages.MESSAGE_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_message_with_env_name_and_id(self, read, check_env_name):
+ self.validate_get_request(messages.URL,
+ params={
+ 'env_name': base.ENV_NAME,
+ 'id': messages.MESSAGE_ID
+ },
+ mocks={
+ read: messages.MESSAGES_WITH_SPECIFIC_ID,
+ check_env_name: False
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=messages.MESSAGES_WITH_SPECIFIC_ID[0])
diff --git a/app/test/api/responders_test/resource/test_monitoring_config_templates.py b/app/test/api/responders_test/resource/test_monitoring_config_templates.py
new file mode 100644
index 0000000..04f413e
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_monitoring_config_templates.py
@@ -0,0 +1,156 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import base
+from test.api.responders_test.test_data import monitoring_config_templates
+from unittest.mock import patch
+
+
+class TestMonitoringConfigTemplates(TestBase):
+
+ def test_get_templates_list_with_unknown_filter(self):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "unknown": "unknown"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_templates_list_with_non_int_order(self):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "order": monitoring_config_templates.NON_INT_ORDER
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_templates_list_with_order(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "order": monitoring_config_templates.INT_ORDER
+ },
+ mocks={
+ read: monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_ORDER
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_ORDER_RESPONSE
+ )
+
+ def test_get_templates_list_with_wrong_side(self):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "side": monitoring_config_templates.WRONG_SIDE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_templates_list_with_side(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "side": monitoring_config_templates.CORRECT_SIDE
+ },
+ mocks={
+ read: monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_SIDE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_SIDE_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_templates_list_with_type(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "type": monitoring_config_templates.TYPE
+ },
+ mocks={
+ read: monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_TYPE
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_TYPE_RESPONSE
+ )
+
+ def test_get_templates_list_with_non_int_page(self):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_templates_list_with_int_page(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: monitoring_config_templates.TEMPLATES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=monitoring_config_templates.
+ TEMPLATES_RESPONSE
+ )
+
+ def test_get_templates_list_with_non_int_pagesize(self):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_templates_list_with_int_pagesize(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: monitoring_config_templates.TEMPLATES
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=monitoring_config_templates.
+ TEMPLATES_RESPONSE
+ )
+
+ def test_get_template_with_wrong_id(self):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "id": monitoring_config_templates.WRONG_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_template_with_unknown_id(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "id": monitoring_config_templates.UNKNOWN_ID
+ },
+ mocks={
+ read: []
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_template_with_id(self, read):
+ self.validate_get_request(monitoring_config_templates.URL,
+ params={
+ "id": monitoring_config_templates.CORRECT_ID
+ },
+ mocks={
+ read: monitoring_config_templates.TEMPLATES_WITH_SPECIFIC_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=monitoring_config_templates.
+ TEMPLATES_WITH_SPECIFIC_ID[0]
+ )
diff --git a/app/test/api/responders_test/resource/test_scans.py b/app/test/api/responders_test/resource/test_scans.py
new file mode 100644
index 0000000..708cd54
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_scans.py
@@ -0,0 +1,239 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import json
+
+from test.api.responders_test.test_data import base
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import scans
+from unittest.mock import patch
+
+
+class TestScans(TestBase):
+
+ def test_get_scans_list_without_env_name(self):
+ self.validate_get_request(scans.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_scans_list_with_invalid_filter(self):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "invalid": "invalid"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_scans_list_with_non_int_page(self):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scans_list_with_int_page(self, read):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: scans.SCANS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scans.SCANS_RESPONSE)
+
+ def test_get_scans_list_with_non_int_pagesize(self):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scans_list_with_int_pagesize(self, read):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: scans.SCANS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scans.SCANS_RESPONSE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scans_list_with_unknown_env(self, read, check_env_name):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.UNKNOWN_ENV
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scans_list_with_base_object(self, read):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "base_object": scans.BASE_OBJECT
+ },
+ mocks={
+ read: scans.SCANS_WITH_SPECIFIC_BASE_OBJ
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scans.
+ SCANS_WITH_SPECIFIC_BASE_OBJ_RESPONSE
+ )
+
+ def test_get_scans_list_with_wrong_status(self):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "status": scans.WRONG_STATUS
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scans_list_with_status(self, read):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "status": scans.CORRECT_STATUS
+ },
+ mocks={
+ read: scans.SCANS_WITH_SPECIFIC_STATUS,
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scans.
+ SCANS_WITH_SPECIFIC_STATUS_RESPONSE
+ )
+
+ def test_get_scan_with_wrong_id(self):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": scans.WRONG_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scan_with_nonexistent_id(self, read, check_env_name):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": scans.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scan_with_unknown_env_and_nonexistent_id(self, read, check_env_name):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.UNKNOWN_ENV,
+ "id": scans.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scan_with_id(self, read):
+ self.validate_get_request(scans.URL,
+ params={
+ "env_name": base.ENV_NAME,
+ "id": scans.CORRECT_ID
+ },
+ mocks={
+ read: scans.SCANS_WITH_SPECIFIC_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scans.SCANS_WITH_SPECIFIC_ID[0]
+ )
+
+ def test_post_scan_with_non_dict_scan(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.NON_DICT_SCAN),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_without_env_name(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITHOUT_ENV),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_post_scan_with_unknown_env_name(self, check_environment_name):
+ self.validate_post_request(scans.URL,
+ mocks={
+ check_environment_name: False
+ },
+ body=json.dumps(scans.SCAN_WITH_UNKNOWN_ENV),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_without_status(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITHOUT_STATUS),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_with_wrong_status(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITH_WRONG_STATUS),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_with_wrong_log_level(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITH_WRONG_LOG_LEVEL),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_with_non_bool_clear(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITH_NON_BOOL_CLEAR),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_with_non_bool_scan_only_inventory(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITH_NON_BOOL_SCAN_ONLY_INVENTORY),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_with_non_bool_scan_only_links(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITH_NON_BOOL_SCAN_ONLY_LINKS),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_scan_with_non_bool_scan_only_cliques(self):
+ self.validate_post_request(scans.URL,
+ body=json.dumps(scans.SCAN_WITH_NON_BOOL_SCAN_ONLY_CLIQUES),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_WRITE)
+ def test_post_scan(self, write, check_env_name):
+ self.validate_post_request(scans.URL,
+ mocks={
+ check_env_name: True,
+ write: None
+ },
+ body=json.dumps(scans.SCAN),
+ expected_code=base.CREATED_CODE)
diff --git a/app/test/api/responders_test/resource/test_scheduled_scans.py b/app/test/api/responders_test/resource/test_scheduled_scans.py
new file mode 100644
index 0000000..23c38de
--- /dev/null
+++ b/app/test/api/responders_test/resource/test_scheduled_scans.py
@@ -0,0 +1,247 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import json
+
+from test.api.responders_test.test_data import base
+from test.api.test_base import TestBase
+from test.api.responders_test.test_data import scheduled_scans
+from unittest.mock import patch
+
+
+class TestScheduledScans(TestBase):
+ def test_get_scheduled_scans_list_without_env_name(self):
+ self.validate_get_request(scheduled_scans.URL,
+ params={},
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_scheduled_scans_list_with_invalid_filter(self):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "invalid": "invalid"
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_scheduled_scans_list_with_non_int_page(self):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "page": base.NON_INT_PAGE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scheduled_scans_list_with_int_page(self, read):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "page": base.INT_PAGE
+ },
+ mocks={
+ read: scheduled_scans.SCHEDULED_SCANS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scheduled_scans.
+ SCHEDULED_SCANS_RESPONSE
+ )
+
+ def test_get_scheduled_scans_list_with_non_int_pagesize(self):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "page_size": base.NON_INT_PAGESIZE
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scheduled_scans_list_with_int_pagesize(self, read):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "page_size": base.INT_PAGESIZE
+ },
+ mocks={
+ read: scheduled_scans.SCHEDULED_SCANS
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scheduled_scans.
+ SCHEDULED_SCANS_RESPONSE
+ )
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scheduled_scans_list_with_unknown_env(self, read, check_env_name):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.UNKNOWN_ENV
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_get_scheduled_scans_list_with_wrong_freq(self):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "freq": scheduled_scans.WRONG_FREQ
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scheduled_scans_list_with_freq(self, read):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "freq": scheduled_scans.CORRECT_FREQ
+ },
+ mocks={
+ read: scheduled_scans.
+ SCHEDULED_SCAN_WITH_SPECIFIC_FREQ,
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scheduled_scans.
+ SCHEDULED_SCAN_WITH_SPECIFIC_FREQ_RESPONSE
+ )
+
+ def test_get_scheduled_scan_with_wrong_id(self):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "id": scheduled_scans.WRONG_ID
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scan_with_nonexistent_id(self, read, check_env_name):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "id": scheduled_scans.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: True
+ },
+ expected_code=base.NOT_FOUND_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scheduled_scan_with_unknown_env_and_nonexistent_id(self, read,
+ check_env_name):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.UNKNOWN_ENV,
+ "id": scheduled_scans.NONEXISTENT_ID
+ },
+ mocks={
+ read: [],
+ check_env_name: False
+ },
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_READ)
+ def test_get_scheduled_scan_with_id(self, read):
+ self.validate_get_request(scheduled_scans.URL,
+ params={
+ "environment": base.ENV_NAME,
+ "id": scheduled_scans.CORRECT_ID
+ },
+ mocks={
+ read: scheduled_scans.
+ SCHEDULED_SCAN_WITH_SPECIFIC_ID
+ },
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=scheduled_scans.
+ SCHEDULED_SCAN_WITH_SPECIFIC_ID[0]
+ )
+
+ def test_post_scheduled_scan_with_non_dict_scheduled_scan(self):
+ self.validate_post_request(scheduled_scans.URL,
+ body=json.dumps(scheduled_scans.
+ NON_DICT_SCHEDULED_SCAN),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ def test_post_bad_scheduled_scans(self):
+ test_cases = [
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITHOUT_ENV
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITHOUT_FREQ
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_WRONG_FREQ
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_WRONG_LOG_LEVEL
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITHOUT_SUBMIT_TIMESTAMP
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_WRONG_SUBMIT_TIMESTAMP
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_NON_BOOL_CLEAR
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_NON_BOOL_SCAN_ONLY_LINKS
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_NON_BOOL_SCAN_ONLY_CLIQUES
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_NON_BOOL_SCAN_ONLY_INVENTORY
+ },
+ {
+ "body": scheduled_scans.
+ SCHEDULED_SCAN_WITH_EXTRA_SCAN_ONLY_FLAGS
+ }
+ ]
+ for test_case in test_cases:
+ self.validate_post_request(scheduled_scans.URL,
+ body=json.dumps(test_case["body"]),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ def test_post_scheduled_scan_with_unknown_env_name(self,
+ check_environment_name):
+ self.validate_post_request(scheduled_scans.URL,
+ mocks={
+ check_environment_name: False
+ },
+ body=json.dumps(scheduled_scans.
+ SCHEDULED_SCAN_WITH_UNKNOWN_ENV),
+ expected_code=base.BAD_REQUEST_CODE)
+
+ @patch(base.RESPONDER_BASE_CHECK_ENVIRONMENT_NAME)
+ @patch(base.RESPONDER_BASE_WRITE)
+ def test_post_scheduled_scan(self, write, check_env_name):
+ self.validate_post_request(scheduled_scans.URL,
+ mocks={
+ check_env_name: True,
+ write: None
+ },
+ body=json.dumps(scheduled_scans.
+ SCHEDULED_SCAN),
+ expected_code=base.CREATED_CODE)
diff --git a/app/test/api/responders_test/test_data/__init__.py b/app/test/api/responders_test/test_data/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/api/responders_test/test_data/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/api/responders_test/test_data/aggregates.py b/app/test/api/responders_test/test_data/aggregates.py
new file mode 100644
index 0000000..52ce985
--- /dev/null
+++ b/app/test/api/responders_test/test_data/aggregates.py
@@ -0,0 +1,67 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+URL = "/aggregates"
+
+CONSTANT_TYPE = "constant"
+ENV_TYPE = "environment"
+MESSAGE_TYPE = "message"
+UNKNOWN_TYPE = "unknown"
+
+CONSTANT_AGGREGATES = [
+ {"name": "type_drivers", "total": 5},
+ {"name": "environment_monitoring_types", "total": 1},
+ {"name": "link_states", "total": 2}
+]
+ENVIRONMENT_AGGREGATES = [
+ {'_id': 'otep', 'total': 3},
+ {'_id': 'instance', 'total': 2},
+ {'_id': 'network_agent', 'total': 6}
+]
+MESSAGE_ENV_AGGREGATES = [
+ {'_id': 'Mirantis-Liberty-API', 'total': 15}
+]
+MESSAGE_LEVEL_AGGREGATES = [
+ {'_id': 'info', 'total': 15}
+]
+
+CONSTANT_AGGREGATES_RESPONSE = {
+ "type": "constant",
+ "aggregates": {
+ "names": {
+ "type_drivers": 5,
+ "environment_monitoring_types": 1,
+ "link_states": 2
+ }
+ }
+ }
+
+ENVIRONMENT_AGGREGATES_RESPONSE = {
+ "aggregates": {
+ "object_types": {
+ "otep": 3,
+ "instance": 2,
+ "network_agent": 6
+ }
+ },
+ "env_name": "Mirantis-Liberty-API",
+ "type": "environment"
+}
+
+MESSAGE_AGGREGATES_RESPONSE = {
+ "aggregates": {
+ "environments": {
+ "Mirantis-Liberty-API": 15
+ },
+ "levels": {
+ "info": 15
+ }
+ },
+ "type": "message"
+ }
diff --git a/app/test/api/responders_test/test_data/base.py b/app/test/api/responders_test/test_data/base.py
new file mode 100644
index 0000000..1e85800
--- /dev/null
+++ b/app/test/api/responders_test/test_data/base.py
@@ -0,0 +1,179 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+# HTTP status code
+SUCCESSFUL_CODE = "200"
+NOT_FOUND_CODE = "404"
+CONFLICT_CODE = "409"
+BAD_REQUEST_CODE = "400"
+UNAUTHORIZED_CODE = "401"
+CREATED_CODE = "201"
+
+ENV_NAME = "Mirantis-Liberty-API"
+UNKNOWN_ENV = "Unkown-Environment"
+NON_INT_PAGE = 1.4
+INT_PAGE = 1
+NON_INT_PAGESIZE = 2.4
+INT_PAGESIZE = 2
+
+WRONG_LINK_TYPE = "instance-host"
+CORRECT_LINK_TYPE= "instance-vnic"
+
+WRONG_LINK_STATE = "wrong"
+CORRECT_LINK_STATE = "up"
+
+WRONG_SCAN_STATUS = "error"
+CORRECT_SCAN_STATUS = "completed"
+
+WRONG_MONITORING_SIDE = "wrong-side"
+CORRECT_MONITORING_SIDE = "client"
+
+WRONG_MESSAGE_SEVERITY = "wrong-severity"
+CORRECT_MESSAGE_SEVERITY = "warn"
+
+WRONG_TYPE_DRIVER = "wrong_type"
+CORRECT_TYPE_DRIVER = "local"
+
+WRONG_MECHANISM_DRIVER = "wrong-mechanism-dirver"
+CORRECT_MECHANISM_DRIVER = "ovs"
+
+WRONG_LOG_LEVEL = "wrong-log-level"
+CORRECT_LOG_LEVEL = "critical"
+
+WRONG_OBJECT_TYPE = "wrong-object-type"
+CORRECT_OBJECT_TYPE = "vnic"
+
+WRONG_ENV_TYPE = ""
+CORRECT_ENV_TYPE = "development"
+
+WRONG_DISTRIBUTION = "wrong-environment"
+CORRECT_DISTRIBUTION = "Mirantis-6.0"
+
+WRONG_OBJECT_ID = "58a2406e6a283a8bee15d43"
+CORRECT_OBJECT_ID = "58a2406e6a283a8bee15d43f"
+
+WRONG_FORMAT_TIME = "2017-01-25T23:34:333+TX0012"
+CORRECT_FORMAT_TIME = "2017-01-25T14:28:32.400Z"
+
+NON_BOOL = "falses"
+BOOL = False
+NON_DICT_OBJ = ""
+
+# fake constants
+CONSTANTS_BY_NAMES = {
+ "link_types": [
+ "instance-vnic",
+ "otep-vconnector",
+ "otep-pnic",
+ "pnic-network",
+ "vedge-otep",
+ "vnic-vconnector",
+ "vconnector-pnic",
+ "vconnector-vedge",
+ "vnic-vedge",
+ "vedge-pnic",
+ "vservice-vnic"
+ ],
+ "link_states": [
+ "up",
+ "down"
+ ],
+ "scan_statuses": [
+ "draft",
+ "pending",
+ "running",
+ "completed",
+ "failed",
+ "aborted"
+ ],
+ "monitoring_sides": [
+ "client",
+ "server"
+ ],
+ "messages_severity": [
+ "panic",
+ "alert",
+ "crit",
+ "error",
+ "warn",
+ "notice",
+ "info",
+ "debug"
+ ],
+ "type_drivers": [
+ "local",
+ "vlan",
+ "vxlan",
+ "gre",
+ "flat"
+ ],
+ "mechanism_drivers": [
+ "ovs",
+ "vpp",
+ "LinuxBridge",
+ "Arista",
+ "Nexus"
+ ],
+ "log_levels": [
+ "critical",
+ "error",
+ "warning",
+ "info",
+ "debug",
+ "notset"
+ ],
+ "object_types": [
+ "vnic",
+ "vconnector",
+ "vedge",
+ "instance",
+ "vservice",
+ "pnic",
+ "network",
+ "port",
+ "otep",
+ "agent"
+ ],
+ "env_types": [
+ "development",
+ "testing",
+ "staging",
+ "production"
+ ],
+ "distributions": [
+ "Mirantis-6.0",
+ "Mirantis-7.0",
+ "Mirantis-8.0",
+ "Mirantis-9.0",
+ "RDO-Juno"
+ ],
+ "environment_operational_status": [
+ "stopped",
+ "running",
+ "error"
+ ],
+ "environment_provision_types": [
+ "None",
+ "Deploy",
+ "Files",
+ "DB"
+ ],
+ "environment_monitoring_types": [
+ "Sensu"
+ ]
+}
+
+# path info
+RESPONDER_BASE_PATH = "api.responders.responder_base.ResponderBase"
+RESPONDER_BASE_GET_OBJECTS_LIST = RESPONDER_BASE_PATH + ".get_objects_list"
+RESPONDER_BASE_GET_OBJECT_BY_ID = RESPONDER_BASE_PATH + ".get_object_by_id"
+RESPONDER_BASE_CHECK_ENVIRONMENT_NAME = RESPONDER_BASE_PATH + ".check_environment_name"
+RESPONDER_BASE_READ = RESPONDER_BASE_PATH + ".read"
+RESPONDER_BASE_WRITE = RESPONDER_BASE_PATH + ".write"
+RESPONDER_BASE_AGGREGATE = RESPONDER_BASE_PATH + ".aggregate"
diff --git a/app/test/api/responders_test/test_data/clique_constraints.py b/app/test/api/responders_test/test_data/clique_constraints.py
new file mode 100644
index 0000000..6f867ae
--- /dev/null
+++ b/app/test/api/responders_test/test_data/clique_constraints.py
@@ -0,0 +1,74 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+URL = "/clique_constraints"
+
+WRONG_ID = base.WRONG_OBJECT_ID
+NONEXISTENT_ID = "576a4176a83d5313f21971f0"
+CORRECT_ID = base.CORRECT_OBJECT_ID
+
+WRONG_FOCAL_POINT_TYPE = base.WRONG_OBJECT_TYPE
+CORRECT_FOCAL_POINT_TYPE = base.CORRECT_OBJECT_TYPE
+
+CONSTRAINT = "network"
+
+CLIQUE_CONSTRAINTS_WITH_SPECIFIC_ID = [
+ {
+ "id": CORRECT_ID
+ }
+]
+
+CLIQUE_CONSTRAINTS_WITH_SPECIFIC_FOCAL_POINT_TYPE = [
+ {
+ "id": "576a4176a83d5313f21971f5",
+ "focal_point_type": CORRECT_FOCAL_POINT_TYPE
+ },
+ {
+ "id": "576ac7069f6ba3074882b2eb",
+ "focal_point_type": CORRECT_FOCAL_POINT_TYPE
+ }
+]
+
+CLIQUE_CONSTRAINTS_WITH_SPECIFIC_FOCAL_POINT_TYPE_RESPONSE = {
+ "clique_constraints": CLIQUE_CONSTRAINTS_WITH_SPECIFIC_FOCAL_POINT_TYPE
+}
+
+CLIQUE_CONSTRAINTS_WITH_SPECIFIC_CONSTRAINT = [
+ {
+ "id": "576a4176a83d5313f21971f5",
+ "constraints": [
+ CONSTRAINT
+ ]
+ },
+ {
+ "id": "576ac7069f6ba3074882b2eb",
+ "constraints": [
+ CONSTRAINT
+ ]
+ }
+]
+
+CLIQUE_CONSTRAINTS_WITH_SPECIFIC_CONSTRAINT_RESPONSE = {
+ "clique_constraints": CLIQUE_CONSTRAINTS_WITH_SPECIFIC_CONSTRAINT
+}
+
+CLIQUE_CONSTRAINTS = [
+ {
+ "id": "576a4176a83d5313f21971f5"
+ },
+ {
+ "id": "576ac7069f6ba3074882b2eb"
+ }
+]
+
+CLIQUE_CONSTRAINTS_RESPONSE = {
+ "clique_constraints": CLIQUE_CONSTRAINTS
+}
diff --git a/app/test/api/responders_test/test_data/clique_types.py b/app/test/api/responders_test/test_data/clique_types.py
new file mode 100644
index 0000000..0fbe839
--- /dev/null
+++ b/app/test/api/responders_test/test_data/clique_types.py
@@ -0,0 +1,170 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+
+URL = "/clique_types"
+
+WRONG_ID = base.WRONG_OBJECT_ID
+NONEXISTENT_ID = "58ca73ae3a8a836d10ff3b44"
+CORRECT_ID = base.CORRECT_OBJECT_ID
+
+WRONG_FOCAL_POINT_TYPE = base.WRONG_OBJECT_TYPE
+CORRECT_FOCAL_POINT_POINT_TYPE = base.CORRECT_OBJECT_TYPE
+
+WRONG_LINK_TYPE = base.WRONG_LINK_TYPE
+NONEXISTENT_LINK_TYPE = "otep-pnic"
+CORRECT_LINK_TYPE = base.CORRECT_LINK_TYPE
+
+CLIQUE_TYPES_WITH_SPECIFIC_ID = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "pnic",
+ "id": CORRECT_ID
+ }
+]
+
+CLIQUE_TYPES_WITH_SPECIFIC_FOCAL_POINT_TYPE = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": CORRECT_FOCAL_POINT_POINT_TYPE,
+ "id": "58ca73ae3a8a836d10ff3b80"
+ },
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": CORRECT_FOCAL_POINT_POINT_TYPE,
+ "id": "58ca73ae3a8a836d10ff3b81"
+ }
+]
+
+CLIQUE_TYPES_WITH_SPECIFIC_FOCAL_POINT_TYPE_RESPONSE = {
+ "clique_types": CLIQUE_TYPES_WITH_SPECIFIC_FOCAL_POINT_TYPE
+}
+
+CLIQUE_TYPES_WITH_SPECIFIC_LINK_TYPE = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "link_types": [
+ CORRECT_LINK_TYPE
+ ],
+ "id": "58ca73ae3a8a836d10ff3b80"
+ },
+ {
+ "environment": "Mirantis-Liberty-API",
+ "link_types": [
+ CORRECT_LINK_TYPE
+ ],
+ "id": "58ca73ae3a8a836d10ff3b81"
+ }
+]
+
+CLIQUE_TYPES_WITH_SPECIFIC_LINK_TYPE_RESPONSE = {
+ "clique_types": CLIQUE_TYPES_WITH_SPECIFIC_LINK_TYPE
+}
+
+CLIQUE_TYPES = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "vnic",
+ "id": "58ca73ae3a8a836d10ff3b80"
+ },
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "vnic",
+ "id": "58ca73ae3a8a836d10ff3b81"
+ }
+]
+
+CLIQUE_TYPES_RESPONSE = {
+ "clique_types": CLIQUE_TYPES
+}
+
+NON_DICT_CLIQUE_TYPE = base.NON_DICT_OBJ
+
+CLIQUE_TYPE_WITHOUT_ENVIRONMENT = {
+ "name": "instance_vconnector_clique",
+ "link_types": [
+ "instance-vnic",
+ "vnic-vconnector"
+ ],
+ "focal_point_type": "instance"
+}
+
+CLIQUE_TYPE_WITH_UNKNOWN_ENVIRONMENT = {
+ "environment": base.UNKNOWN_ENV,
+ "id": "589a3969761b0555a3ef6093",
+ "name": "instance_vconnector_clique",
+ "link_types": [
+ "instance-vnic",
+ "vnic-vconnector"
+ ],
+ "focal_point_type": "instance"
+}
+
+CLIQUE_TYPE_WITHOUT_FOCAL_POINT_TYPE = {
+ "environment": "Mirantis-Liberty-API",
+ "name": "instance_vconnector_clique",
+ "link_types": [
+ "instance-vnic",
+ "vnic-vconnector"
+ ]
+}
+
+CLIQUE_TYPE_WITH_WRONG_FOCAL_POINT_TYPE = {
+ "environment": "Mirantis-Liberty-API",
+ "name": "instance_vconnector_clique",
+ "link_types": [
+ "instance-vnic",
+ "vnic-vconnector"
+ ],
+ "focal_point_type": WRONG_FOCAL_POINT_TYPE
+}
+
+CLIQUE_TYPE_WITHOUT_LINK_TYPES = {
+ "environment": "Mirantis-Liberty-API",
+ "name": "instance_vconnector_clique",
+ "focal_point_type": "instance"
+}
+
+CLIQUE_TYPE_WITH_NON_LIST_LINK_TYPES = {
+ "environment": "Mirantis-Liberty-API",
+ "name": "instance_vconnector_clique",
+ "link_types": "instance-vnic",
+ "focal_point_type": "instance"
+}
+
+CLIQUE_TYPE_WITH_WRONG_LINK_TYPE = {
+ "environment": "Mirantis-Liberty-API",
+ "name": "instance_vconnector_clique",
+ "link_types": [
+ WRONG_LINK_TYPE,
+ "vnic-vconnector"
+ ],
+ "focal_point_type": "instance"
+}
+
+CLIQUE_TYPE_WITHOUT_NAME = {
+ "environment": "Mirantis-Liberty-API",
+ "link_types": [
+ "instance-vnic",
+ "vnic-vconnector",
+ ],
+ "focal_point_type": "instance"
+}
+
+CLIQUE_TYPE = {
+ "environment": "Mirantis-Liberty-API",
+ "name": "instance_vconnector_clique",
+ "link_types": [
+ "instance-vnic",
+ "vnic-vconnector"
+ ],
+ "focal_point_type": "instance"
+}
diff --git a/app/test/api/responders_test/test_data/cliques.py b/app/test/api/responders_test/test_data/cliques.py
new file mode 100644
index 0000000..e1995cd
--- /dev/null
+++ b/app/test/api/responders_test/test_data/cliques.py
@@ -0,0 +1,171 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+URL = "/cliques"
+
+WRONG_CLIQUE_ID = "58a2406e6a283a8bee15d43"
+CORRECT_CLIQUE_ID = "58a2406e6a283a8bee15d43f"
+NONEXISTENT_CLIQUE_ID = "58a2406e6a283a8bee15d43e"
+
+WRONG_FOCAL_POINT = "58a2406e6a283a8bee15d43"
+CORRECT_FOCAL_POINT = "58a2406e6a283a8bee15d43f"
+
+WRONG_LINK_ID = "58a2406e6a283a8bee15d43"
+CORRECT_LINK_ID = "58a2406e6a283a8bee15d43f"
+NONEXISTENT_LINK_ID = "58a2406e6a283a8bee15d43e"
+
+WRONG_FOCAL_POINT_TYPE = base.WRONG_OBJECT_TYPE
+CORRECT_FOCAL_POINT_TYPE = base.CORRECT_OBJECT_TYPE
+
+WRONG_LINK_TYPE = base.WRONG_LINK_TYPE
+CORRECT_LINK_TYPE = base.CORRECT_LINK_TYPE
+
+CLIQUES_WITH_SPECIFIC_ID = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "vnic",
+ "id": CORRECT_CLIQUE_ID
+ }
+]
+
+CLIQUES_WITH_SPECIFIC_FOCAL_POINT_TYPE = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": CORRECT_FOCAL_POINT_TYPE,
+ "id": "576c119a3f4173144c7a75c5"
+ },
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": CORRECT_FOCAL_POINT_TYPE,
+ "id": "576c119a3f4173144c7a75cc6"
+ }
+]
+
+CLIQUES_WITH_SPECIFIC_FOCAL_POINT_TYPE_RESPONSE = {
+ "cliques": CLIQUES_WITH_SPECIFIC_FOCAL_POINT_TYPE
+}
+
+CLIQUES_WITH_SPECIFIC_FOCAL_POINT = [
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point": CORRECT_FOCAL_POINT,
+ "id": "576c119a3f4173144c7a75c5"
+ },
+ {
+ "environment": "Mirantis-Liberty-API",
+ "focal_point": CORRECT_FOCAL_POINT,
+ "id": "576c119a3f4173144c7a758e"
+ }
+]
+
+CLIQUES_WITH_SPECIFIC_FOCAL_POINT_RESPONSE = {
+ "cliques": CLIQUES_WITH_SPECIFIC_FOCAL_POINT
+}
+
+CLIQUES_WITH_SPECIFIC_LINK_TYPE = [
+ {
+ "links_detailed": [
+ {
+ "link_type": CORRECT_LINK_TYPE,
+ "_id": "58a2405a6a283a8bee15d42f"
+ },
+ {
+ "link_type": "vnic-vconnector",
+ "_id": "58a240056a283a8bee15d3f2"
+ }
+ ],
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "vnic",
+ "id": "576c119a3f4173144c7a75c5"
+ },
+ {
+ "links_detailed": [
+ {
+ "link_type": CORRECT_LINK_TYPE,
+ "_id": "58a2405a6a283a8bee15d42f"
+ }
+ ],
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "pnic",
+ "id": "576c119a3f4173144c7a75c7"
+ }
+]
+
+CLIQUES_WITH_SPECIFIC_LINK_TYPE_RESPONSE = {
+ "cliques": CLIQUES_WITH_SPECIFIC_LINK_TYPE
+}
+
+CLIQUES_WITH_SPECIFIC_LINK_ID = [
+ {
+ "links_detailed": [
+ {
+ "_id": CORRECT_LINK_ID
+ },
+ {
+ "_id": "58a240056a283a8bee15d3f2"
+ }
+ ],
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "vnic",
+ "id": "576c119a3f4173144c7a75c5"
+ },
+ {
+ "links_detailed": [
+ {
+ "_id": CORRECT_LINK_ID
+ }
+ ],
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "pnic",
+ "id": "576c119a3f4173144c7a75c7"
+ }
+]
+
+CLIQUES_WITH_SPECIFIC_LINK_ID_RESPONSE = {
+ "cliques": CLIQUES_WITH_SPECIFIC_LINK_ID
+}
+
+# response
+CLIQUES = [{
+ "links_detailed": [
+ {
+ "link_type": "instance-vnic",
+ "_id": "58a2405a6a283a8bee15d42f"
+ },
+ {
+ "link_type": "vnic-vconnector",
+ "_id": "58a240056a283a8bee15d3f2"
+ }
+ ],
+ "environment": "Mirantis-Liberty-API",
+ "focal_point_type": "vnic",
+ "id": "576c119a3f4173144c7a75c5"
+ },
+ {
+ "links_detailed": [
+ {
+ "link_type": "instance-vnic",
+ "_id": "58a2405a6a283a8bee15d42f"
+ },
+ {
+ "link_type": "vnic-vconnector",
+ "_id": "58a240056a283a8bee15d3f2"
+ }
+ ],
+ "environment": "Miratis-Liberty-API",
+ "focal_point_type": "pnic",
+ "id": "576c119a3f4173144c7a75c6"
+ }
+]
+
+CLIQUES_RESPONSE = {
+ "cliques": CLIQUES
+}
diff --git a/app/test/api/responders_test/test_data/constants.py b/app/test/api/responders_test/test_data/constants.py
new file mode 100644
index 0000000..9293209
--- /dev/null
+++ b/app/test/api/responders_test/test_data/constants.py
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+URL = "/constants"
+UNKNOWN_NAME = "unknown constant"
+NAME = "distributions"
+CONSTANTS_WITH_SPECIFIC_NAME = [{
+ "id": "YmPDAQAchr39KjECQ",
+ "name": NAME,
+ "data": [{
+ "value": "Canonical-icehouse",
+ "label": "Canonical-icehouse"
+ }, {
+ "value": "Canonical-juno",
+ "label": "Canonical-juno"
+ }],
+}]
diff --git a/app/test/api/responders_test/test_data/environment_configs.py b/app/test/api/responders_test/test_data/environment_configs.py
new file mode 100644
index 0000000..2a67fb6
--- /dev/null
+++ b/app/test/api/responders_test/test_data/environment_configs.py
@@ -0,0 +1,221 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+
+URL = "/environment_configs"
+
+NAME = "Mirantis-Liberty-API"
+UNKNOWN_NAME = "UNKNOWN NAME"
+WRONG_DISTRIBUTION = base.WRONG_DISTRIBUTION
+CORRECT_DISTRIBUTION = base.CORRECT_DISTRIBUTION
+WRONG_MECHANISM_DRIVER = base.WRONG_MECHANISM_DRIVER
+CORRECT_MECHANISM_DRIVER = base.CORRECT_MECHANISM_DRIVER
+WRONG_TYPE_DRIVER = base.WRONG_TYPE_DRIVER
+CORRECT_TYPE_DRIVER = base.CORRECT_TYPE_DRIVER
+USER = "WS7j8oTbWPf3LbNne"
+NON_BOOL_LISTEN = NON_BOOL_SCANNED = \
+ NON_BOOL_MONITORING_SETUP_DONE = base.NON_BOOL
+
+BOOL_LISTEN = BOOL_SCANNED = \
+ BOOL_MONITORING_SETUP_DONE = base.BOOL
+
+ENV_CONFIGS = [
+ {
+ "distribution": "Mirantis-8.0",
+ "name": "Mirantis-Liberty-API"
+ },
+ {
+ "distribution": "Mirantis-9.0",
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_RESPONSE = {
+ "environment_configs": ENV_CONFIGS
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_NAME = [
+ {
+ "distribution": "Mirantis-8.0",
+ "name": NAME
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_DISTRIBUTION = [
+ {
+ "distribution": CORRECT_DISTRIBUTION,
+ "name": "Mirantis-Liberty-API",
+ },
+ {
+ "distribution": CORRECT_DISTRIBUTION,
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_DISTRIBUTION_RESPONSE = {
+ "environment_configs": ENV_CONFIGS_WITH_SPECIFIC_DISTRIBUTION
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_MECHANISM_DRIVER = [
+ {
+ "name": "Mirantis-Liberty-API",
+ "mechanism_drivers": [
+ CORRECT_MECHANISM_DRIVER
+ ]
+ },
+ {
+ "name": "Mirantis-Liberty",
+ "mechanism_drivers": [
+ CORRECT_MECHANISM_DRIVER
+ ]
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_MECHANISM_DRIVER_RESPONSE = {
+ "environment_configs": ENV_CONFIGS_WITH_SPECIFIC_MECHANISM_DRIVER
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_TYPE_DRIVER = [
+ {
+ "type_drivers": CORRECT_TYPE_DRIVER,
+ "name": "Mirantis-Liberty-API",
+ },
+ {
+ "type_drivers": CORRECT_TYPE_DRIVER,
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_TYPE_DRIVER_RESPONSE = {
+ 'environment_configs': ENV_CONFIGS_WITH_SPECIFIC_TYPE_DRIVER
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_USER = [
+ {
+ "user": USER,
+ "name": "Mirantis-Liberty-API",
+ },
+ {
+ "user": USER,
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_USER_RESPONSE = {
+ "environment_configs": ENV_CONFIGS_WITH_SPECIFIC_USER
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_LISTEN = [
+ {
+ "listen": BOOL_LISTEN,
+ "name": "Mirantis-Liberty-API",
+ },
+ {
+ "listen": BOOL_LISTEN,
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_LISTEN_RESPONSE = {
+ "environment_configs": ENV_CONFIGS_WITH_SPECIFIC_LISTEN
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_SCANNED = [
+ {
+ "scanned": BOOL_SCANNED,
+ "name": "Mirantis-Liberty-API",
+ },
+ {
+ "scanned": BOOL_SCANNED,
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_SCANNED_RESPONSE = {
+ "environment_configs": ENV_CONFIGS_WITH_SPECIFIC_SCANNED
+}
+
+ENV_CONFIGS_WITH_SPECIFIC_MONITORING_SETUP_DONE = [
+ {
+ "monitoring_setup_done": BOOL_MONITORING_SETUP_DONE,
+ "name": "Mirantis-Liberty-API",
+ },
+ {
+ "monitoring_setup_done": BOOL_MONITORING_SETUP_DONE,
+ "name": "Mirantis-Liberty"
+ }
+]
+
+ENV_CONFIGS_WITH_SPECIFIC_MONITORING_SETUP_DONE_RESPONSE = {
+ "environment_configs": ENV_CONFIGS_WITH_SPECIFIC_MONITORING_SETUP_DONE
+}
+
+ENV_CONFIG = {
+ "app_path": "/home/korenlev/Calipso/app/",
+ "configuration": [
+ {
+ "host": "10.56.20.239",
+ "name": "mysql",
+ "password": "G1VKEbcqKZXoPthrtNma2D9Y",
+ "port": "3307",
+ "user": "root"
+ },
+ {
+ "name": "OpenStack",
+ "host": "10.56.20.239",
+ "admin_token": "wLWefGuD0uYJ7tqkeEScdnNo",
+ "port": "5000",
+ "user": "admin",
+ "pwd": "admin"
+ },
+ {
+ "host": "10.56.20.239",
+ "key": "/etc/calipso/keys/Mirantis-Liberty-id_rsa",
+ "name": "CLI",
+ "user": "root"
+ },
+ {
+ "host": "10.56.20.239",
+ "name": "AMQP",
+ "password": "YVWMiKMshZhlJCGqFu5PdT9d",
+ "port": "5673",
+ "user": "nova"
+ },
+ {
+ "config_folder": "/tmp/sensu_test",
+ "provision": "None",
+ "env_type": "development",
+ "name": "Monitoring",
+ "api_port": "4567",
+ "rabbitmq_port": "5671",
+ "rabbitmq_pass": "sensuaccess",
+ "rabbitmq_user": "sensu",
+ "ssh_port": "20022",
+ "ssh_user": "root",
+ "ssh_password": "calipso",
+ "server_ip": "korlev-calipso-staging1.cisco.com",
+ "server_name": "calipso-sensu",
+ "type": "Sensu"
+ }
+ ],
+ "distribution": "Mirantis-8.0",
+ "last_scanned": "2017-03-16T11:14:54Z",
+ "listen": True,
+ "mechanism_drivers": [
+ "ovs"
+ ],
+ "name": "Mirantis-Liberty",
+ "operational": "running",
+ "scanned": True,
+ "type": "environment",
+ "type_drivers": "vxlan",
+ "user": "WS7j8oTbWPf3LbNne"
+}
diff --git a/app/test/api/responders_test/test_data/inventory.py b/app/test/api/responders_test/test_data/inventory.py
new file mode 100644
index 0000000..47d611d
--- /dev/null
+++ b/app/test/api/responders_test/test_data/inventory.py
@@ -0,0 +1,37 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+URL = "/inventory"
+
+ID = "RegionOne-aggregates"
+NONEXISTENT_ID = "Unkown-Id"
+
+
+OBJECTS_LIST = [
+ {
+ "id": "Mirantis-Liberty-regions",
+ "name": "Regions",
+ "name_path": "/Mirantis-Liberty-API/Regions"
+ },
+ {
+ "id": "Mirantis-Liberty-projects",
+ "name": "Projects",
+ "name_path": "/Mirantis-Liberty-API/Projects"
+ }
+]
+
+OBJECT_IDS_RESPONSE = {
+ "objects": OBJECTS_LIST
+}
+
+
+OBJECTS = [{
+ "environment": "Mirantis-Liberty-API",
+ "id": "RegionOne-aggregates"
+}]
diff --git a/app/test/api/responders_test/test_data/links.py b/app/test/api/responders_test/test_data/links.py
new file mode 100644
index 0000000..e71c02d
--- /dev/null
+++ b/app/test/api/responders_test/test_data/links.py
@@ -0,0 +1,90 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+
+URL = "/links"
+
+UNKNOWN_HOST = "unknown host"
+
+WRONG_TYPE = base.WRONG_LINK_TYPE
+CORRECT_TYPE = base.CORRECT_LINK_TYPE
+
+WRONG_STATE = base.WRONG_LINK_STATE
+CORRECT_STATE = base.CORRECT_LINK_STATE
+
+LINK_ID = "58ca73ae3a8a836d10ff3b45"
+WRONG_LINK_ID = "58ca73ae3a8a836d10ff3b4"
+NONEXISTENT_LINK_ID = "58ca73ae3a8a836d10ff3b46"
+
+LINKS_WITH_SPECIFIC_TYPE = [
+ {
+ "id": "58ca73ae3a8a836d10ff3bb5",
+ "host": "node-1.cisco.com",
+ "link_type": CORRECT_TYPE,
+ "link_name": "Segment-103",
+ "environment": "Mirantis-Liberty-API"
+ },
+ {
+ "id": "58ca73ae3a8a836d10ff3b4d",
+ "host": "node-1.cisco.com",
+ "link_type": CORRECT_TYPE,
+ "link_name": "Segment-104",
+ "environment": "Mirantis-Liberty-API"
+ }
+]
+
+
+LINKS_WITH_SPECIFIC_STATE = [
+ {
+ "id": "58ca73ae3a8a836d10ff3bb5",
+ "host": "node-1.cisco.com",
+ "state": CORRECT_STATE,
+ "environment": "Mirantis-Liberty-API"
+ },
+ {
+ "id": "58ca73ae3a8a836d10ff3b4d",
+ "host": "node-1.cisco.com",
+ "state": CORRECT_STATE,
+ "environment": "Mirantis-Liberty-API"
+ }
+]
+
+LINKS_WITH_SPECIFIC_STATE_RESPONSE = {
+ "links": LINKS_WITH_SPECIFIC_STATE
+}
+
+LINKS_WITH_SPECIFIC_TYPE_RESPONSE = {
+ "links": LINKS_WITH_SPECIFIC_TYPE
+}
+
+LINKS_WITH_SPECIFIC_ID = [
+ {
+ "id": LINK_ID,
+ "host": "node-1.cisco.com",
+ "link_type": "pnic-network",
+ "link_name": "Segment-103",
+ "environment": "Mirantis-Liberty-API"
+ }
+]
+
+LINKS = [
+ {
+ "id": "58ca73ae3a8a836d10ff3b45",
+ "host": "node-1.cisco.com",
+ "link_type": "pnic-network",
+ "link_name": "Segment-103",
+ "environment": "Mirantis-Liberty-API"
+ }
+]
+
+LINKS_LIST_RESPONSE = {
+ "links": LINKS
+}
diff --git a/app/test/api/responders_test/test_data/messages.py b/app/test/api/responders_test/test_data/messages.py
new file mode 100644
index 0000000..b7b5abd
--- /dev/null
+++ b/app/test/api/responders_test/test_data/messages.py
@@ -0,0 +1,108 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+# url
+URL = "/messages"
+
+NONEXISTENT_MESSAGE_ID = "80b5e074-0f1a-4b67-810c-fa9c92d41a9f"
+MESSAGE_ID = "80b5e074-0f1a-4b67-810c-fa9c92d41a98"
+
+WRONG_SEVERITY = base.WRONG_MESSAGE_SEVERITY
+CORRECT_SEVERITY = base.CORRECT_MESSAGE_SEVERITY
+
+WRONG_RELATED_OBJECT_TYPE = base.WRONG_OBJECT_TYPE
+CORRECT_RELATED_OBJECT_TYPE = base.CORRECT_OBJECT_TYPE
+
+RELATED_OBJECT = "instance"
+NONEXISTENT_RELATED_OBJECT = "nonexistent-instance"
+
+WRONG_FORMAT_TIME = base.WRONG_FORMAT_TIME
+CORRECT_FORMAT_TIME = base.CORRECT_FORMAT_TIME
+
+MESSAGES_WITH_SPECIFIC_TIME = [
+ {
+ "level": "info",
+ "environment": "Mirantis-Liberty-API",
+ "id": "3c64fe31-ca3b-49a3-b5d3-c485d7a452e7",
+ "source_system": "OpenStack",
+ "timestamp": CORRECT_FORMAT_TIME
+ }
+]
+
+MESSAGES_WITH_SPECIFIC_TIME_RESPONSE = {
+ "messages": MESSAGES_WITH_SPECIFIC_TIME
+}
+
+MESSAGES_WITH_SPECIFIC_SEVERITY = [
+ {
+ "level": CORRECT_SEVERITY,
+ "environment": "Mirantis-Liberty-API",
+ "id": "3c64fe31-ca3b-49a3-b5d3-c485d7a452e7",
+ "source_system": "OpenStack"
+ },
+ {
+ "level": CORRECT_SEVERITY,
+ "environment": "Mirantis-Liberty-API",
+ "id": "c7071ec0-04db-4820-92ff-3ed2b916738f",
+ "source_system": "OpenStack"
+ },
+]
+
+MESSAGES_WITH_SPECIFIC_SEVERITY_RESPONSE = {
+ "messages": MESSAGES_WITH_SPECIFIC_SEVERITY
+}
+
+MESSAGES_WITH_SPECIFIC_RELATED_OBJECT_TYPE = [
+ {
+ "level": "info",
+ "environment": "Mirantis-Liberty-API",
+ "related_object_type": CORRECT_RELATED_OBJECT_TYPE,
+ "id": "3c64fe31-ca3b-49a3-b5d3-c485d7a452e7"
+ },
+ {
+ "level": "error",
+ "environment": "Mirantis-Liberty-API",
+ "related_object_type": CORRECT_RELATED_OBJECT_TYPE,
+ "id": "c7071ec0-04db-4820-92ff-3ed2b916738f"
+ },
+]
+
+MESSAGES_WITH_SPECIFIC_RELATED_OBJECT_TYPE_RESPONSE = {
+ "messages": MESSAGES_WITH_SPECIFIC_RELATED_OBJECT_TYPE
+}
+
+MESSAGES_WITH_SPECIFIC_ID = [
+ {
+ "level": "info",
+ "environment": "Mirantis-Liberty",
+ "id": MESSAGE_ID,
+ "source_system": "OpenStack"
+ }
+]
+
+MESSAGES = [
+ {
+ "level": "info",
+ "environment": "Mirantis-Liberty",
+ "id": "3c64fe31-ca3b-49a3-b5d3-c485d7a452e7",
+ "source_system": "OpenStack"
+ },
+ {
+ "level": "info",
+ "environment": "Mirantis-Liberty",
+ "id": "c7071ec0-04db-4820-92ff-3ed2b916738f",
+ "source_system": "OpenStack"
+ },
+]
+
+MESSAGES_RESPONSE = {
+ "messages": MESSAGES
+}
diff --git a/app/test/api/responders_test/test_data/monitoring_config_templates.py b/app/test/api/responders_test/test_data/monitoring_config_templates.py
new file mode 100644
index 0000000..0f387a4
--- /dev/null
+++ b/app/test/api/responders_test/test_data/monitoring_config_templates.py
@@ -0,0 +1,98 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+
+URL = "/monitoring_config_templates"
+
+WRONG_ID = base.WRONG_OBJECT_ID
+UNKNOWN_ID = "583711893e149c14785d6da5"
+CORRECT_ID = base.CORRECT_OBJECT_ID
+
+NON_INT_ORDER = 1.3
+INT_ORDER = 1
+
+WRONG_SIDE = base.WRONG_MONITORING_SIDE
+CORRECT_SIDE = base.CORRECT_MONITORING_SIDE
+
+TYPE = "client.json"
+
+TEMPLATES_WITH_SPECIFIC_ORDER = [
+ {
+ "order": INT_ORDER,
+ "id": "583711893e149c14785d6daa"
+ },
+ {
+ "order": INT_ORDER,
+ "id": "583711893e149c14785d6da7"
+ }
+]
+
+TEMPLATES_WITH_SPECIFIC_ORDER_RESPONSE = {
+ "monitoring_config_templates":
+ TEMPLATES_WITH_SPECIFIC_ORDER
+}
+
+TEMPLATES_WITH_SPECIFIC_SIDE = [
+ {
+ "side": CORRECT_SIDE,
+ "id": "583711893e149c14785d6daa"
+ },
+ {
+ "side": CORRECT_SIDE,
+ "id": "583711893e149c14785d6da7"
+ }
+]
+
+TEMPLATES_WITH_SPECIFIC_SIDE_RESPONSE = {
+ "monitoring_config_templates":
+ TEMPLATES_WITH_SPECIFIC_SIDE
+}
+
+TEMPLATES_WITH_SPECIFIC_TYPE = [
+ {
+ "type": TYPE,
+ "id": "583711893e149c14785d6daa"
+ },
+ {
+ "type": TYPE,
+ "id": "583711893e149c14785d6da7"
+ }
+]
+
+TEMPLATES_WITH_SPECIFIC_TYPE_RESPONSE = {
+ "monitoring_config_templates":
+ TEMPLATES_WITH_SPECIFIC_TYPE
+}
+
+TEMPLATES_WITH_SPECIFIC_ID = [
+ {
+ "type": "rabbitmq.json",
+ "side": "client",
+ "id": CORRECT_ID
+ }
+]
+
+TEMPLATES = [
+ {
+ "type": "rabbitmq.json",
+ "side": "client",
+ "id": "583711893e149c14785d6daa"
+ },
+ {
+ "type": "rabbitmq.json",
+ "side": "client",
+ "id": "583711893e149c14785d6da7"
+ }
+]
+
+TEMPLATES_RESPONSE = {
+ "monitoring_config_templates": TEMPLATES
+}
diff --git a/app/test/api/responders_test/test_data/scans.py b/app/test/api/responders_test/test_data/scans.py
new file mode 100644
index 0000000..479d371
--- /dev/null
+++ b/app/test/api/responders_test/test_data/scans.py
@@ -0,0 +1,187 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+URL = "/scans"
+
+WRONG_ID = base.WRONG_OBJECT_ID
+NONEXISTENT_ID = "58c96a075eb66a121cc4e750"
+CORRECT_ID = base.CORRECT_OBJECT_ID
+
+BASE_OBJECT = "node-2.cisco.com"
+
+WRONG_STATUS = base.WRONG_SCAN_STATUS
+CORRECT_STATUS = base.CORRECT_SCAN_STATUS
+
+SCANS = [
+ {
+ "status": "pending",
+ "environment": "Mirantis-Liberty-API",
+ "id": "58c96a075eb66a121cc4e75f",
+ },
+ {
+ "status": "completed",
+ "environment": "Mirantis-Liberty-API",
+ "id": "58c96a075eb66a121cc4e75e",
+ "scan_completed": True
+ }
+]
+
+SCANS_RESPONSE = {
+ "scans": SCANS
+}
+
+SCANS_WITH_SPECIFIC_ID = [
+ {
+ "status": "pending",
+ "environment": "Mirantis-Liberty-API",
+ "id": CORRECT_ID,
+ }
+]
+
+SCANS_WITH_SPECIFIC_BASE_OBJ = [
+ {
+ "status": "pending",
+ "environment": "Mirantis-Liberty-API",
+ "id": "58c96a075eb66a121cc4e75f",
+ "object_id": BASE_OBJECT
+ },
+ {
+ "status": "completed",
+ "environment": "Mirantis-Liberty-API",
+ "id": "58c96a075eb66a121cc4e75e",
+ "object_id": BASE_OBJECT,
+ "scan_completed": True
+ }
+]
+
+SCANS_WITH_SPECIFIC_BASE_OBJ_RESPONSE = {
+ "scans": SCANS_WITH_SPECIFIC_BASE_OBJ
+}
+
+SCANS_WITH_SPECIFIC_STATUS = [
+ {
+ "status": CORRECT_STATUS,
+ "environment": "Mirantis-Liberty-API",
+ "id": "58c96a075eb66a121cc4e75f",
+ "scan_completed": True
+ },
+ {
+ "status": CORRECT_STATUS,
+ "environment": "Mirantis-Liberty-API",
+ "id": "58c96a075eb66a121cc4e75e",
+ "scan_completed": True
+ }
+]
+
+SCANS_WITH_SPECIFIC_STATUS_RESPONSE = {
+ "scans": SCANS_WITH_SPECIFIC_STATUS
+}
+
+NON_DICT_SCAN = base.NON_DICT_OBJ
+
+SCAN = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_inventory": True,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITHOUT_ENV = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_inventory": True,
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITH_UNKNOWN_ENV = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_inventory": True,
+ "environment": base.UNKNOWN_ENV,
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITHOUT_STATUS = {
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_inventory": True,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITH_WRONG_STATUS = {
+ "status": WRONG_STATUS,
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_inventory": True,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITH_WRONG_LOG_LEVEL = {
+ "status": "pending",
+ "log_level": base.WRONG_LOG_LEVEL,
+ "clear": True,
+ "scan_only_inventory": True,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITH_NON_BOOL_CLEAR = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": base.NON_BOOL,
+ "scan_only_inventory": True,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+
+SCAN_WITH_NON_BOOL_SCAN_ONLY_INVENTORY = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_inventory": base.NON_BOOL,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITH_NON_BOOL_SCAN_ONLY_LINKS = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_links": base.NON_BOOL,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
+
+SCAN_WITH_NON_BOOL_SCAN_ONLY_CLIQUES = {
+ "status": "pending",
+ "log_level": "warning",
+ "clear": True,
+ "scan_only_cliques": base.NON_BOOL,
+ "environment": "Mirantis-Liberty-API",
+ "inventory": "inventory",
+ "object_id": "ff"
+}
diff --git a/app/test/api/responders_test/test_data/scheduled_scans.py b/app/test/api/responders_test/test_data/scheduled_scans.py
new file mode 100644
index 0000000..1019572
--- /dev/null
+++ b/app/test/api/responders_test/test_data/scheduled_scans.py
@@ -0,0 +1,138 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.api.responders_test.test_data import base
+
+URL = "/scheduled_scans"
+WRONG_FREQ = "wrong_freq"
+CORRECT_FREQ = "WEEKLY"
+WRONG_ID = base.WRONG_OBJECT_ID
+NONEXISTENT_ID = "58c96a075eb66a121cc4e750"
+CORRECT_ID = "ff4d3e80e42e886bef13a084"
+NON_DICT_SCHEDULED_SCAN = ""
+
+
+SCHEDULED_SCANS = [
+ {
+ "id": "ff4d3e80e42e886bef13a084",
+ "environment": base.ENV_NAME,
+ "scheduled_timestamp": "2017-07-24T12:45:03.784+0000",
+ "freq": "WEEKLY"
+ },
+ {
+ "id": "58e4e1aa6df71e971324ea62",
+ "environment": base.ENV_NAME,
+ "scheduled_timestamp": "2017-07-24T12:45:03.784+0000",
+ "freq": "WEEKLY"
+ }
+]
+
+SCHEDULED_SCANS_RESPONSE = {
+ "scheduled_scans": SCHEDULED_SCANS
+}
+
+SCHEDULED_SCAN_WITH_SPECIFIC_FREQ = [{
+ "id": "ff4d3e80e42e886bef13a084",
+ "environment": base.ENV_NAME,
+ "scheduled_timestamp": "2017-07-24T12:45:03.784+0000",
+ "freq": CORRECT_FREQ
+}]
+
+SCHEDULED_SCAN_WITH_SPECIFIC_FREQ_RESPONSE = {
+ "scheduled_scans": SCHEDULED_SCAN_WITH_SPECIFIC_FREQ
+}
+
+SCHEDULED_SCAN_WITH_SPECIFIC_ID = [{
+ "id": CORRECT_ID,
+ "environment": base.ENV_NAME,
+ "scheduled_timestamp": "2017-07-24T12:45:03.784+0000",
+ "freq": CORRECT_FREQ
+}]
+
+SCHEDULED_SCAN = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000"
+}
+
+SCHEDULED_SCAN_WITHOUT_ENV = {
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000"
+}
+
+SCHEDULED_SCAN_WITH_UNKNOWN_ENV = {
+ "environment": base.UNKNOWN_ENV,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000"
+}
+
+SCHEDULED_SCAN_WITHOUT_FREQ = {
+ "environment": base.ENV_NAME,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000"
+}
+
+SCHEDULED_SCAN_WITHOUT_SUBMIT_TIMESTAMP = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+}
+
+SCHEDULED_SCAN_WITH_WRONG_FREQ = {
+ "environment": base.ENV_NAME,
+ "freq": WRONG_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000"
+}
+
+SCHEDULED_SCAN_WITH_WRONG_LOG_LEVEL = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "log_level": base.WRONG_LOG_LEVEL,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000"
+}
+
+SCHEDULED_SCAN_WITH_WRONG_SUBMIT_TIMESTAMP = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": base.WRONG_FORMAT_TIME
+}
+
+SCHEDULED_SCAN_WITH_NON_BOOL_CLEAR = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000",
+ "clear": base.NON_BOOL
+}
+
+SCHEDULED_SCAN_WITH_NON_BOOL_SCAN_ONLY_LINKS = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000",
+ "scan_only_links": base.NON_BOOL
+}
+
+SCHEDULED_SCAN_WITH_NON_BOOL_SCAN_ONLY_CLIQUES = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000",
+ "scan_only_cliques": base.NON_BOOL
+}
+
+SCHEDULED_SCAN_WITH_NON_BOOL_SCAN_ONLY_INVENTORY = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000",
+ "scan_only_inventory": base.NON_BOOL
+}
+
+SCHEDULED_SCAN_WITH_EXTRA_SCAN_ONLY_FLAGS = {
+ "environment": base.ENV_NAME,
+ "freq": CORRECT_FREQ,
+ "submit_timestamp": "2017-07-24T12:45:03.784+0000",
+ "scan_only_links": True,
+ "scan_only_inventory": True
+}
diff --git a/app/test/api/responders_test/test_data/tokens.py b/app/test/api/responders_test/test_data/tokens.py
new file mode 100644
index 0000000..8d9960d
--- /dev/null
+++ b/app/test/api/responders_test/test_data/tokens.py
@@ -0,0 +1,83 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+URL = '/auth/tokens'
+
+AUTH_OBJ_WITHOUT_AUTH = {
+
+}
+
+AUTH_OBJ_WITHOUT_METHODS = {
+ 'auth': {}
+}
+
+AUTH_OBJ_WITHOUT_CREDENTIALS = {
+ 'auth': {
+ 'methods': ['credentials']
+ }
+}
+
+AUTH_OBJ_WITHOUT_TOKEN = {
+ 'auth': {
+ 'methods': ['token']
+ }
+}
+
+AUTH_OBJ_WITH_WRONG_CREDENTIALS = {
+ 'auth': {
+ 'methods': ['credentials'],
+ 'credentials': {
+ 'username': 'wrong_user',
+ 'password': 'password'
+ }
+ }
+}
+
+AUTH_OBJ_WITH_WRONG_TOKEN = {
+ 'auth': {
+ 'methods': ['token'],
+ 'token': 'wrong_token'
+ }
+}
+
+AUTH_OBJ_WITH_CORRECT_CREDENTIALS = {
+ 'auth': {
+ 'methods': ['credentials'],
+ 'credentials': {
+ 'username': 'wrong_user',
+ 'password': 'password'
+ }
+ }
+}
+
+AUTH_OBJ_WITH_CORRECT_TOKEN = {
+ 'auth': {
+ 'methods': ['token'],
+ 'token': '17dfa88789aa47f6bb8501865d905f13'
+ }
+}
+
+HEADER_WITHOUT_TOKEN = {
+
+}
+
+HEADER_WITH_WRONG_TOKEN = {
+ 'X-Auth-Token': 'wrong token'
+}
+
+HEADER_WITH_CORRECT_TOKEN = {
+ 'X-Auth-Token': '17dfa88789aa47f6bb8501865d905f13'
+}
+
+AUTH_BASE_PATH = 'api.auth.auth.Auth'
+AUTH_GET_TOKEN = AUTH_BASE_PATH + '.get_token'
+AUTH_WRITE_TOKEN = AUTH_BASE_PATH + '.write_token'
+AUTH_DELETE_TOKEN = AUTH_BASE_PATH + '.delete_token'
+AUTH_VALIDATE_CREDENTIALS = AUTH_BASE_PATH + '.validate_credentials'
+AUTH_VALIDATE_TOKEN = AUTH_BASE_PATH + '.validate_token'
diff --git a/app/test/api/test_base.py b/app/test/api/test_base.py
new file mode 100644
index 0000000..c126b2b
--- /dev/null
+++ b/app/test/api/test_base.py
@@ -0,0 +1,101 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import copy
+
+
+from api.app import App
+from api.middleware.authentication import AuthenticationMiddleware
+from api.responders.responder_base import ResponderBase
+from api.backends.ldap_access import LDAPAccess
+from falcon.testing import TestCase
+from test.api.responders_test.test_data import base
+from unittest.mock import MagicMock
+from utils.mongo_access import MongoAccess
+
+
+def mock_auth_method(*args):
+ return None
+
+
+class TestBase(TestCase):
+
+ def setUp(self, authenticate=False):
+ super().setUp()
+ # mock
+ self.authenticate = authenticate
+ if not authenticate:
+ self.original_auth_method = AuthenticationMiddleware.process_request
+ AuthenticationMiddleware.process_request = mock_auth_method
+
+ ResponderBase.get_constants_by_name = MagicMock(side_effect=
+ lambda name: base.CONSTANTS_BY_NAMES[name])
+ # mock mongo access
+ MongoAccess.mongo_connect = MagicMock()
+ MongoAccess.db = MagicMock()
+ MongoAccess.client = MagicMock()
+ # mock ldap access
+ LDAPAccess.get_ldap_params = MagicMock()
+ LDAPAccess.connect_ldap_server = MagicMock()
+
+ log_level = 'debug'
+ self.app = App(log_level=log_level).get_app()
+
+ def validate_get_request(self, url, params={}, headers=None, mocks={},
+ side_effects={},
+ expected_code=base.SUCCESSFUL_CODE,
+ expected_response=None):
+ self.validate_request("GET", url, params, headers, "",
+ mocks, side_effects,
+ expected_code,
+ expected_response)
+
+ def validate_request(self, action, url, params, headers, body,
+ mocks, side_effects, expected_code,
+ expected_response):
+ for mock_method, mock_data in mocks.items():
+ mock_method.return_value = mock_data
+
+ for mock_method, side_effect in side_effects.items():
+ mock_method.side_effect = side_effect
+
+ result = self.simulate_request(action, url, params=params, headers=headers, body=body)
+ self.assertEqual(result.status, expected_code)
+ if expected_response:
+ self.assertEqual(result.json, expected_response)
+
+ def validate_post_request(self, url, headers={}, body="", mocks={},
+ side_effects={},
+ expected_code=base.CREATED_CODE, expected_response=None):
+ self.validate_request("POST", url, {}, headers, body, mocks, side_effects,
+ expected_code, expected_response)
+
+ def validate_delete_request(self, url, params={}, headers={}, mocks={},
+ side_effects={},
+ expected_code=base.SUCCESSFUL_CODE, expected_response=None):
+ self.validate_request("DELETE", url, params, headers, "",
+ mocks, side_effects,
+ expected_code,
+ expected_response)
+
+ def get_updated_data(self, original_data, deleted_keys=[], updates={}):
+ copy_data = copy.deepcopy(original_data)
+
+ for key in deleted_keys:
+ del copy_data[key]
+
+ for key, value in updates.items():
+ copy_data[key] = value
+
+ return copy_data
+
+ def tearDown(self):
+ # if the authentication method has been mocked, it needs to be reset after test
+ if not self.authenticate:
+ AuthenticationMiddleware.process_request = self.original_auth_method
diff --git a/app/test/event_based_scan/__init__.py b/app/test/event_based_scan/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/event_based_scan/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/event_based_scan/config/__init__.py b/app/test/event_based_scan/config/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/event_based_scan/config/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/event_based_scan/config/test_config.py b/app/test/event_based_scan/config/test_config.py
new file mode 100644
index 0000000..176fd48
--- /dev/null
+++ b/app/test/event_based_scan/config/test_config.py
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+# local config info for test.
+
+
+MONGODB_CONFIG = 'your-mongo-config-path-here'
+
+ENV_CONFIG = 'your-env-name-here'
+
+COLLECTION_CONFIG = 'your-inventory-collection-name-here'
diff --git a/app/test/event_based_scan/test_data/__init__.py b/app/test/event_based_scan/test_data/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/event_based_scan/test_data/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/event_based_scan/test_data/event_payload_instance_add.py b/app/test/event_based_scan/test_data/event_payload_instance_add.py
new file mode 100644
index 0000000..316444a
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_instance_add.py
@@ -0,0 +1,122 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_INSTANCE_ADD = {
+ 'publisher_id': 'compute.node-251.cisco.com', '_context_resource_uuid': None,
+ '_context_instance_lock_checked': False,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_request_id': 'req-432fccc8-4d13-4e62-8639-c99acee82cb3',
+ '_context_show_deleted': False,
+ '_context_timestamp': '2016-09-08T22:01:41.724236',
+ '_unique_id': '537fc5b27c244479a69819a4a435723b',
+ '_context_roles': ['_member_', 'admin'], '_context_read_only': False,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_project_name': 'calipso-project',
+ '_context_project_domain': None, 'event_type': 'compute.instance.update',
+ '_context_service_catalog': [{'endpoints': [
+ {'internalURL': 'http://192.168.0.2:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'publicURL': 'http://172.16.0.3:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'adminURL': 'http://192.168.0.2:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'region': 'RegionOne'}],
+ 'type': 'volumev2',
+ 'name': 'cinderv2'},
+ {'endpoints': [{
+ 'internalURL': 'http://192.168.0.2:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'publicURL': 'http://172.16.0.3:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'adminURL': 'http://192.168.0.2:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'region': 'RegionOne'}],
+ 'type': 'volume',
+ 'name': 'cinder'}],
+ 'payload': {'instance_type': 'm1.micro', 'progress': '', 'display_name': 'test8',
+ 'kernel_id': '',
+ 'new_task_state': None, 'old_display_name': 'name-change',
+ 'state_description': '',
+ 'old_state': 'building', 'ramdisk_id': '',
+ 'created_at': '2016-09-08 16:32:46+00:00',
+ 'os_type': None,
+ 'ephemeral_gb': 0, 'launched_at': '2016-09-08T16:25:08.000000',
+ 'instance_flavor_id': 'f068e24b-5d7e-4819-b5ca-89a33834a918',
+ 'image_meta': {'min_ram': '64', 'container_format': 'bare', 'min_disk': '0',
+ 'disk_format': 'qcow2',
+ 'base_image_ref': 'c6f490c4-3656-43c6-8d03-b4e66bd249f9'},
+ 'audit_period_beginning': '2016-09-01T00:00:00.000000', 'memory_mb': 64,
+ 'cell_name': '',
+ 'access_ip_v6': None, 'instance_type_id': 6, 'reservation_id': 'r-bycutzve',
+ 'access_ip_v4': None,
+ 'hostname': 'chengli-test-vm1', 'metadata': {},
+ 'user_id': '13baa553aae44adca6615e711fd2f6d9',
+ 'availability_zone': 'calipso-zone',
+ 'instance_id': '27a87908-bc1b-45cc-9238-09ad1ae686a7', 'deleted_at': '',
+ 'image_ref_url': 'http://172.16.0.4:9292/images/c6f490c4-3656-43c6-8d03-b4e66bd249f9',
+ 'host': 'node-252.cisco.com', 'vcpus': 1, 'state': 'active',
+ 'old_task_state': None,
+ 'architecture': None,
+ 'terminated_at': '', 'root_gb': 0,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'node': 'node-252.cisco.com', 'bandwidth': {}, 'disk_gb': 0,
+ 'audit_period_ending': '2016-09-08T22:01:43.165282'},
+ '_context_quota_class': None,
+ '_context_is_admin': True, '_context_read_deleted': 'no',
+ 'timestamp': '2016-09-08 22:01:43.189907',
+ 'message_id': '4a9068c6-dcd1-4d6c-81d7-db866e07c1ff', 'priority': 'INFO',
+ '_context_domain': None,
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_remote_address': '192.168.0.2', '_context_user_domain': None,
+ '_context_auth_token': '''gAAAAABX0d-R0Q4zIrznmZ_L8BT0m4r_lp-7eOr4IenbKz511g2maNo8qhIb86HtA7S
+ VGsEJvy4KRcNIGlVRdmGyXBYm3kEuakQXTsXLxvyQeTtgZ9UgnLLXhQvMLbA2gwaimVpyRljq92R7Y7CwnNFLjibhOiYs
+ NlvBqitJkaRaQa4sg4xCN2tBj32Re-jRu6dR_sIA-haT''',
+ '_context_user_name': 'admin'}
+
+INSTANCES_ROOT = {
+ "create_object": True,
+ "environment": ENV_CONFIG,
+ "id": "node-252.cisco.com-instances",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones" +
+ "/calipso-zone/node-252.cisco.com/node-252.cisco.com-instances",
+ "name": "Instances",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/calipso-zone/node-252.cisco.com/Instances",
+ "object_name": "Instances",
+ "parent_id": "node-252.cisco.com",
+ "parent_type": "host",
+ "show_in_tree": True,
+ "text": "Instances",
+ "type": "instances_folder"
+}
+
+INSTANCE_DOCUMENT = {
+ 'projects': ['calipso-project'],
+ 'network': [],
+ 'host': 'node-252.cisco.com', 'parent_type': 'instances_folder',
+ '_id': '57e421194a0a8a3fbe3bd2d0', 'mac_address': 'fa:16:3e:5e:9e:db', 'type': 'instance',
+ 'name': 'name-change',
+ 'uuid': '27a87908-bc1b-45cc-9238-09ad1ae686a7', 'environment': ENV_CONFIG,
+ 'ip_address': '192.168.0.4', 'local_name': 'instance-00000020', 'object_name': 'test8',
+ 'parent_id': 'node-223.cisco.com-instances', 'project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'name_path': '/'+ENV_CONFIG+'/Regions/RegionOne/Availability Zones' +
+ '/calipso-zone/node-252.cisco.com/Instances/name-change',
+ 'id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'id_path': '/'+ENV_CONFIG+'/'+ENV_CONFIG+'-regions/RegionOne/RegionOne-availability_zones/calipso-zone' +
+ '/node-223.cisco.com/node-223.cisco.com-instances/27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'show_in_tree': True}
+
+HOST = {
+ 'name_path': '/'+ ENV_CONFIG +'/Regions/RegionOne/Availability Zones/calipso-zone/node-252.cisco.com',
+ 'id_path': '/'+ENV_CONFIG+ '/'+ENV_CONFIG+'-regions/RegionOne/' +
+ 'RegionOne-availability_zones/calipso-zone/node-252.cisco.com',
+ 'object_name': 'node-252.cisco.com', 'last_scanned': 0,
+ 'type': 'host', 'environment': ENV_CONFIG, 'host': 'node-252.cisco.com', 'id': 'node-252.cisco.com',
+ 'ip_address': '192.168.0.4', 'name': 'node-252.cisco.com', 'host_type': ['Compute'],
+ 'services': {'nova-compute': {'updated_at': '2016-09-26T22:47:09.000000', 'active': True, 'available': True}},
+ 'show_in_tree': True, 'zone': 'calipso-zone', 'os_id': '1',
+ 'parent_type': 'availability_zone', 'parent_id': 'calipso-zone'
+}
diff --git a/app/test/event_based_scan/test_data/event_payload_instance_delete.py b/app/test/event_based_scan/test_data/event_payload_instance_delete.py
new file mode 100644
index 0000000..a94de63
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_instance_delete.py
@@ -0,0 +1,97 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+
+EVENT_PAYLOAD_INSTANCE_DELETE = {
+ 'publisher_id': 'compute.node-253.cisco.com', '_context_resource_uuid': None,
+ '_context_instance_lock_checked': False,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_request_id': 'req-432fccc8-4d13-4e62-8639-c99acee82cb3',
+ '_context_show_deleted': False,
+ '_context_timestamp': '2016-09-08T22:01:41.724236',
+ '_unique_id': '537fc5b27c244479a69819a4a435723b',
+ '_context_roles': ['_member_', 'admin'], '_context_read_only': False,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_project_name': 'calipso-project',
+ '_context_project_domain': None, 'event_type': 'compute.instance.update',
+ '_context_service_catalog': [{'endpoints': [
+ {'internalURL': 'http://192.168.0.2:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'publicURL': 'http://172.16.0.3:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'adminURL': 'http://192.168.0.2:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'region': 'RegionOne'}],
+ 'type': 'volumev2',
+ 'name': 'cinderv2'},
+ {'endpoints': [{
+ 'internalURL': 'http://192.168.0.2:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'publicURL': 'http://172.16.0.3:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'adminURL': 'http://192.168.0.2:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'region': 'RegionOne'}],
+ 'type': 'volume',
+ 'name': 'cinder'}],
+ 'payload': {'instance_type': 'm1.micro', 'progress': '', 'display_name': 'test8',
+ 'kernel_id': '',
+ 'new_task_state': None, 'old_display_name': 'name-change',
+ 'state_description': '',
+ 'old_state': 'active', 'ramdisk_id': '',
+ 'created_at': '2016-09-08 16:32:46+00:00',
+ 'os_type': None,
+ 'ephemeral_gb': 0, 'launched_at': '2016-09-08T16:25:08.000000',
+ 'instance_flavor_id': 'f068e24b-5d7e-4819-b5ca-89a33834a918',
+ 'image_meta': {'min_ram': '64', 'container_format': 'bare',
+ 'min_disk': '0',
+ 'disk_format': 'qcow2',
+ 'base_image_ref': 'c6f490c4-3656-43c6-8d03-b4e66bd249f9'},
+ 'audit_period_beginning': '2016-09-01T00:00:00.000000', 'memory_mb': 64,
+ 'cell_name': '',
+ 'access_ip_v6': None, 'instance_type_id': 6,
+ 'reservation_id': 'r-bycutzve',
+ 'access_ip_v4': None,
+ 'hostname': 'chengli-test-vm1', 'metadata': {},
+ 'user_id': '13baa553aae44adca6615e711fd2f6d9',
+ 'availability_zone': 'calipso-zone',
+ 'instance_id': '27a87908-bc1b-45cc-9238-09ad1ae686a7', 'deleted_at': '',
+ 'image_ref_url': 'http://172.16.0.4:9292/images/c6f490c4-3656-43c6-8d03-b4e66bd249f9',
+ 'host': 'node-252.cisco.com', 'vcpus': 1, 'state': 'deleted',
+ 'old_task_state': None,
+ 'architecture': None,
+ 'terminated_at': '', 'root_gb': 0,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'node': 'node-252.cisco.com', 'bandwidth': {}, 'disk_gb': 0,
+ 'audit_period_ending': '2016-09-08T22:01:43.165282'},
+ '_context_quota_class': None,
+ '_context_is_admin': True, '_context_read_deleted': 'no',
+ 'timestamp': '2016-09-08 22:01:43.189907',
+ 'message_id': '4a9068c6-dcd1-4d6c-81d7-db866e07c1ff', 'priority': 'INFO',
+ '_context_domain': None,
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_remote_address': '192.168.0.2', '_context_user_domain': None,
+ '_context_auth_token': '''gAAAAABX0d-R0Q4zIrznmZ_L8BT0m4r_lp-7eOr4IenbKz511g2maNo8qhIb86HtA7S
+ VGsEJvy4KRcNIGlVRdmGyXBYm3kEuakQXTsXLxvyQeTtgZ9UgnLLXhQvMLbA2gwaimVpyRljq92R7Y7CwnNFLjibhOiYs
+ NlvBqitJkaRaQa4sg4xCN2tBj32Re-jRu6dR_sIA-haT''',
+ '_context_user_name': 'admin'}
+
+
+INSTANCE_DOCUMENT = {
+ 'projects': ['calipso-project'],
+ 'network': ['b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe', '7e59b726-d6f4-451a-a574-c67a920ff627'],
+ 'host': 'node-252.cisco.com', 'parent_type': 'instances_folder',
+ '_id': '57e421194a0a8a3fbe3bd2d0', 'mac_address': 'fa:16:3e:5e:9e:db', 'type': 'instance',
+ 'name': 'test8',
+ 'uuid': '27a87908-bc1b-45cc-9238-09ad1ae686a7', 'environment': ENV_CONFIG,
+ 'ip_address': '192.168.0.4', 'local_name': 'instance-00000020', 'object_name': 'test8',
+ 'parent_id': 'node-252.cisco.com-instances', 'project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne/Availability Zones/calipso-zone/node-252.cisco.com/Instances/test8',
+ 'id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne/RegionOne-availability_zones/calipso-zone/'+
+ 'node-252.cisco.com/node-252.cisco.com-instances/27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'show_in_tree': True}
diff --git a/app/test/event_based_scan/test_data/event_payload_instance_update.py b/app/test/event_based_scan/test_data/event_payload_instance_update.py
new file mode 100644
index 0000000..8b4f1af
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_instance_update.py
@@ -0,0 +1,99 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+
+EVENT_PAYLOAD_INSTANCE_UPDATE = {
+ 'publisher_id': 'compute.node-222.cisco.com', '_context_resource_uuid': None,
+ '_context_instance_lock_checked': False,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_request_id': 'req-432fccc8-4d13-4e62-8639-c99acee82cb3',
+ '_context_show_deleted': False,
+ '_context_timestamp': '2016-09-08T22:01:41.724236',
+ '_unique_id': '537fc5b27c244479a69819a4a435723b',
+ '_context_roles': ['_member_', 'admin'], '_context_read_only': False,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_project_name': 'calipso-project',
+ '_context_project_domain': None, 'event_type': 'compute.instance.update',
+ '_context_service_catalog': [
+ {'endpoints': [
+ {'internalURL': 'http://192.168.0.2:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'publicURL': 'http://172.16.0.3:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'adminURL': 'http://192.168.0.2:8776/v2/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'region': 'RegionOne'}],
+ 'type': 'volumev2',
+ 'name': 'cinderv2'},
+ {'endpoints': [{
+ 'internalURL': 'http://192.168.0.2:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'publicURL': 'http://172.16.0.3:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'adminURL': 'http://192.168.0.2:8776/v1/75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'region': 'RegionOne'}],
+ 'type': 'volume',
+ 'name': 'cinder'}],
+ 'payload': {'instance_type': 'm1.micro', 'progress': '', 'display_name': 'test8',
+ 'kernel_id': '',
+ 'new_task_state': None, 'old_display_name': 'name-change',
+ 'state_description': '',
+ 'old_state': 'active', 'ramdisk_id': '',
+ 'created_at': '2016-09-08 16:32:46+00:00',
+ 'os_type': None,
+ 'ephemeral_gb': 0, 'launched_at': '2016-09-08T16:25:08.000000',
+ 'instance_flavor_id': 'f068e24b-5d7e-4819-b5ca-89a33834a918',
+ 'image_meta': {'min_ram': '64', 'container_format': 'bare',
+ 'min_disk': '0',
+ 'disk_format': 'qcow2',
+ 'base_image_ref': 'c6f490c4-3656-43c6-8d03-b4e66bd249f9'},
+ 'audit_period_beginning': '2016-09-01T00:00:00.000000', 'memory_mb': 64,
+ 'cell_name': '',
+ 'access_ip_v6': None, 'instance_type_id': 6,
+ 'reservation_id': 'r-bycutzve',
+ 'access_ip_v4': None,
+ 'hostname': 'chengli-test-vm1', 'metadata': {},
+ 'user_id': '13baa553aae44adca6615e711fd2f6d9',
+ 'availability_zone': 'calipso-zone',
+ 'instance_id': '27a87908-bc1b-45cc-9238-09ad1ae686a7', 'deleted_at': '',
+ 'image_ref_url': 'http://172.16.0.4:9292/images/c6f490c4-3656-43c6-8d03-b4e66bd249f9',
+ 'host': 'node-223.cisco.com', 'vcpus': 1, 'state': 'active',
+ 'old_task_state': None,
+ 'architecture': None,
+ 'terminated_at': '', 'root_gb': 0,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'node': 'node-223.cisco.com', 'bandwidth': {}, 'disk_gb': 0,
+ 'audit_period_ending': '2016-09-08T22:01:43.165282'},
+ '_context_quota_class': None,
+ '_context_is_admin': True, '_context_read_deleted': 'no',
+ 'timestamp': '2016-09-08 22:01:43.189907',
+ 'message_id': '4a9068c6-dcd1-4d6c-81d7-db866e07c1ff', 'priority': 'INFO',
+ '_context_domain': None,
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_remote_address': '192.168.0.2', '_context_user_domain': None,
+ '_context_auth_token': '''gAAAAABX0d-R0Q4zIrznmZ_L8BT0m4r_lp-7eOr4IenbKz511g2maNo8qhIb86HtA7S
+ VGsEJvy4KRcNIGlVRdmGyXBYm3kEuakQXTsXLxvyQeTtgZ9UgnLLXhQvMLbA2gwaimVpyRljq92R7Y7CwnNFLjibhOiYs
+ NlvBqitJkaRaQa4sg4xCN2tBj32Re-jRu6dR_sIA-haT''',
+ '_context_user_name': 'admin'}
+
+
+INSTANCE_DOCUMENT = {
+ 'projects': ['calipso-project'],
+ 'network': ['b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe', '7e59b726-d6f4-451a-a574-c67a920ff627'],
+ 'host': 'node-223.cisco.com', 'parent_type': 'instances_folder',
+ '_id': '57e421194a0a8a3fbe3bd2d0', 'mac_address': 'fa:16:3e:5e:9e:db', 'type': 'instance',
+ 'name': 'name-change',
+ 'uuid': '27a87908-bc1b-45cc-9238-09ad1ae686a7', 'environment': ENV_CONFIG,
+ 'ip_address': '192.168.0.4', 'local_name': 'instance-00000020', 'object_name': 'name-change',
+ 'parent_id': 'node-223.cisco.com-instances', 'project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'name_path': '/'+ENV_CONFIG+'/Regions/RegionOne/Availability Zones' +
+ '/calipso-zone/node-223.cisco.com/Instances/name-change',
+ 'id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'id_path': '/'+ENV_CONFIG+'/'+ENV_CONFIG+'-regions/RegionOne/RegionOne-availability_zones/calipso-zone' +
+ '/node-223.cisco.com/node-223.cisco.com-instances/27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'show_in_tree': True}
diff --git a/app/test/event_based_scan/test_data/event_payload_interface_add.py b/app/test/event_based_scan/test_data/event_payload_interface_add.py
new file mode 100644
index 0000000..263b010
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_interface_add.py
@@ -0,0 +1,350 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_INTERFACE_ADD = {
+ '_context_timestamp': '2016-10-26 21:52:18.893134', '_context_project_name': 'calipso-project',
+ 'publisher_id': 'network.node-251.cisco.com', 'timestamp': '2016-10-26 21:52:22.377165',
+ '_context_user_name': 'admin',
+ '_context_roles': ['_member_', 'admin'], '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_unique_id': '44d8a3be1078455b9f73e76cdda9f67a', 'priority': 'INFO',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_user_domain': None,
+ '_context_show_deleted': False,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_is_admin': True, 'message_id': 'b81eb79f-f5d2-4bc8-b68e-81650cca1c92', 'payload': {
+ 'router_interface': {'port_id': '1233445-75b6-4c05-9480-4bc648845c6f',
+ 'id': 'c57216ca-c1c4-430d-a045-32851ca879e3',
+ 'subnet_ids': ['6f6ef3b5-76c9-4f70-81e5-f3cc196db025'],
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'subnet_id': '6f6ef3b5-76c9-4f70-81e5-f3cc196db025'}}, '_context_domain': None,
+ '_context_read_only': False, '_context_resource_uuid': None, 'event_type': 'router.interface.create',
+ '_context_request_id': 'req-260fe6fd-0e14-42de-8dbc-acd480015166', '_context_project_domain': None,
+ '_context_tenant_name': 'calipso-project',
+ '_context_auth_token': 'gAAAAABYERgkK8sR80wFsQywjt8vwG0caJW5oxfsWNURcDaYAxy0O6P0u2QQczoMuHBAZa-Ga8T1b3O-5p7p' +
+ 'jw-vAyI1z5whuY7i-hJSl2II6WUX2-9dy7BALQgxhCGpe60atLcyTl-rW6o_TKc3f-ppvqtiul4UTlzH9OtY' +
+ 'N7b-CezaywYDCIMuzGbThPARd9ilQR2B6DuE'}
+
+NETWORK_DOC = {
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.12.0/24"
+ ],
+ "environment": ENV_CONFIG,
+ "id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0a" +
+ "e4973c8375ddf40-networks/55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "last_scanned": 0,
+ "mtu": 0,
+ "name": "please_connect",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/please_connect",
+ "network": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "object_name": "please_connect",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "calipso-project",
+ "provider:network_type": "vxlan",
+ "provider:physical_network": None,
+ "provider:segmentation_id": 23,
+ "router:external": False,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnet_ids": [
+ "6f6ef3b5-76c9-4f70-81e5-f3cc196db025"
+ ],
+ "subnets": {
+ "1234": {
+ "cidr": "172.16.12.0/24",
+ "network_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "allocation_pools": [
+ {
+ "start": "172.16.12.2",
+ "end": "172.16.12.254"
+ }
+ ],
+ "id": "6f6ef3b5-76c9-4f70-81e5-f3cc196db025",
+ "enable_dhcp": True,
+ "ipv6_address_mode": None,
+ "name": "1234",
+ "host_routes": [
+
+ ],
+ "ipv6_ra_mode": None,
+ "gateway_ip": "172.16.12.1",
+ "ip_version": 4,
+ "subnetpool_id": None,
+ "dns_nameservers": [
+
+ ],
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ },
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "network"
+}
+
+EVENT_PAYLOAD_REGION = {
+ 'RegionOne': {
+ 'object_name': 'RegionOne', 'id': 'RegionOne', 'name': 'RegionOne',
+ 'environment': ENV_CONFIG,
+ 'last_scanned': 0,
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne',
+ 'parent_id': ENV_CONFIG + '-regions', 'parent_type': 'regions_folder',
+ 'endpoints': {'nova': {'id': '274cbbd9fd6d4311b78e78dd3a1df51f',
+ 'adminURL': 'http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'compute',
+ 'publicURL': 'http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da'},
+ 'heat-cfn': {'id': '0f04ec6ed49f4940822161bf677bdfb2',
+ 'adminURL': 'http://192.168.0.2:8000/v1',
+ 'service_type': 'cloudformation',
+ 'publicURL': 'http://172.16.0.3:8000/v1',
+ 'internalURL': 'http://192.168.0.2:8000/v1'},
+ 'nova_ec2': {'id': '390dddc753cc4d378b489129d06c4b7d',
+ 'adminURL': 'http://192.168.0.2:8773/services/Admin',
+ 'service_type': 'ec2',
+ 'publicURL': 'http://172.16.0.3:8773/services/Cloud',
+ 'internalURL': 'http://192.168.0.2:8773/services/Cloud'},
+ 'glance': {'id': '475c6c77a94e4e63a5a0f0e767f697a8',
+ 'adminURL': 'http://192.168.0.2:9292',
+ 'service_type': 'image',
+ 'publicURL': 'http://172.16.0.3:9292',
+ 'internalURL': 'http://192.168.0.2:9292'},
+ 'swift': {'id': '12e78e06595f48339baebdb5d4309c70',
+ 'adminURL': 'http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'object-store',
+ 'publicURL': 'http://172.16.0.3:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da'},
+ 'swift_s3': {'id': '4f655c8f2bef46a0a7ba4a20bba53666',
+ 'adminURL': 'http://192.168.0.2:8080',
+ 'service_type': 's3',
+ 'publicURL': 'http://172.16.0.3:8080',
+ 'internalURL': 'http://192.168.0.2:8080'},
+ 'keystone': {'id': '404cceb349614eb39857742970408301',
+ 'adminURL': 'http://192.168.0.2:35357/v2.0',
+ 'service_type': 'identity',
+ 'publicURL': 'http://172.16.0.3:5000/v2.0',
+ 'internalURL': 'http://192.168.0.2:5000/v2.0'},
+ 'cinderv2': {'id': '2c30937688e944889db4a64fab6816e6',
+ 'adminURL': 'http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'volumev2',
+ 'publicURL': 'http://172.16.0.3:8776/v2/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da'},
+ 'novav3': {'id': '1df917160dfb4ce5b469764fde22b3ab',
+ 'adminURL': 'http://192.168.0.2:8774/v3',
+ 'service_type': 'computev3',
+ 'publicURL': 'http://172.16.0.3:8774/v3',
+ 'internalURL': 'http://192.168.0.2:8774/v3'},
+ 'ceilometer': {'id': '617177a3dcb64560a5a79ab0a91a7225',
+ 'adminURL': 'http://192.168.0.2:8777',
+ 'service_type': 'metering',
+ 'publicURL': 'http://172.16.0.3:8777',
+ 'internalURL': 'http://192.168.0.2:8777'},
+ 'neutron': {'id': '8dc28584da224c4b9671171ead3c982a',
+ 'adminURL': 'http://192.168.0.2:9696',
+ 'service_type': 'network',
+ 'publicURL': 'http://172.16.0.3:9696',
+ 'internalURL': 'http://192.168.0.2:9696'},
+ 'cinder': {'id': '05643f2cf9094265b432376571851841',
+ 'adminURL': 'http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'volume',
+ 'publicURL': 'http://172.16.0.3:8776/v1/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da'},
+ 'heat': {'id': '9e60268a5aaf422d9e42f0caab0a19b4',
+ 'adminURL': 'http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'orchestration',
+ 'publicURL': 'http://172.16.0.3:8004/v1/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da'}},
+ 'show_in_tree': True,
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne',
+ 'type': 'region'}}
+
+PORT_DOC = {
+ "admin_state_up": True,
+ "allowed_address_pairs": [
+
+ ],
+ "binding:host_id": "",
+ "binding:profile": {
+
+ },
+ "binding:vif_details": {
+
+ },
+ "binding:vif_type": "unbound",
+ "binding:vnic_type": "normal",
+ "device_id": "c57216ca-c1c4-430d-a045-32851ca879e3",
+ "device_owner": "network:router_interface",
+ "dns_assignment": [
+ {
+ "hostname": "host-172-16-10-1",
+ "ip_address": "172.16.10.1",
+ "fqdn": "host-172-16-10-1.openstacklocal."
+ }
+ ],
+ "dns_name": "",
+ "environment": ENV_CONFIG,
+ "extra_dhcp_opts": [
+
+ ],
+ "fixed_ips": [
+ {
+ "ip_address": "172.16.10.1",
+ "subnet_id": "6f6ef3b5-76c9-4f70-81e5-f3cc196db025"
+ }
+ ],
+ "id": "1233445-75b6-4c05-9480-4bc648845c6f",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0a" +
+ "e4973c8375ddf40-networks/55550a69-24eb-47f5-a458-3aa086cc71c2/55550a69-24eb-47f5-a458-3aa086cc71c2" +
+ "-ports/1233445-75b6-4c05-9480-4bc648845c6f",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:13:b2:aa",
+ "master_parent_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "master_parent_type": "network",
+ "name": "fa:16:3e:13:b2:aa",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/test_interface/Ports" +
+ "/1233445-75b6-4c05-9480-4bc648845c6f",
+ "network_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "object_name": "1233445-75b6-4c05-9480-4bc648845c6f",
+ "parent_id": "55550a69-24eb-47f5-a458-3aa086cc71c2-ports",
+ "parent_text": "Ports",
+ "parent_type": "ports_folder",
+ "port_security_enabled": False,
+ "project": "calipso-project",
+ "security_groups": [
+
+ ],
+ "status": "DOWN",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "port"
+}
+
+ROUTER_DOCUMENT = {
+ "admin_state_up": True,
+ "enable_snat": 1,
+ "environment": ENV_CONFIG,
+ "gw_port_id": "e2f31c24-d0f9-499e-a8b1-883941543aa4",
+ "host": "node-251.cisco.com",
+ "id": "node-251.cisco.com-qrouter-c57216ca-c1c4-430d-a045-32851ca879e3",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-251.cisco.com/node-251.cisco.com-vservices/node-251.cisco.com-vservices-routers/node-251.cisco.com-qrouter-bde87" +
+ "a5a-7968-4f3b-952c-e87681a96078",
+ "last_scanned": 0,
+ "local_service_id": "node-251.cisco.com-qrouter-c57216ca-c1c4-430d-a045-32851ca879e3",
+ "master_parent_id": "node-251.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "1234",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com/" +
+ "Vservices/Gateways/router-1234",
+ "network": [
+ "55550a69-24eb-47f5-a458-3aa086cc71c2"
+ ],
+ "object_name": "router-1234",
+ "parent_id": "node-251.cisco.com-vservices-routers",
+ "parent_text": "Gateways",
+ "parent_type": "vservice_routers_folder",
+ "service_type": "router",
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "vservice"
+}
+
+HOST = {
+ "config": {
+ "use_namespaces": True,
+ "handle_internal_only_routers": True,
+ "ex_gw_ports": 2,
+ "agent_mode": "legacy",
+ "log_agent_heartbeats": False,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "router_id": "",
+ "gateway_external_network_id": "",
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "routers": 2,
+ "interfaces": 4
+ },
+ "environment": ENV_CONFIG,
+ "host": "node-251.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-251.cisco.com",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones" +
+ "/internal/node-251.cisco.com",
+ "last_scanned": 0,
+ "name": "node-251.cisco.com",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com",
+ "object_name": "node-251.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-conductor": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:08.000000"
+ },
+ "nova-scheduler": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:38.000000"
+ },
+ "nova-cert": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:29.000000"
+ },
+ "nova-consoleauth": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:37.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+}
+
+VNIC_DOCS = [{
+ "IP Address": "172.16.10.2",
+ "IPv6 Address": "fe80::f816:3eff:fe96:5066/64",
+ "cidr": "172.16.10.0/25",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:96:50:66\ninet addr:172.16.10.2 Bcast:172.16.10.127 " +
+ "Mask:255.255.255.128\ninet6 addr: fe80::f816:3eff:fe96:5066/64 Scope:Link\nUP BROADCAST RUNNING " +
+ "MULTICAST MTU:1450 Metric:1\nRX packets:17 errors:0 dropped:2 overruns:0 frame:0\nTX packets:8 " +
+ "errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:1593 " +
+ "(1.5 KB) TX bytes:648 (648.0 B)\n",
+ "environment": ENV_CONFIG,
+ "host": "node-251.cisco.com",
+ "id": "tapca33c645-5b",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-251.cisco.com/node-251.cisco.com-vservices/node-251.cisco.com-vservices-dhcps/qdhcp-911fe57e" +
+ "-1ddd-4151-9dc7-6b578ab357b1/qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics/tapca33c645-5b",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:13:b2:aa",
+ "name": "tapca33c645-5b",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com/" +
+ "Vservices/DHCP servers/dhcp-test_interface/vNICs/tapca33c645-5b",
+ "netmask": "255.255.255.128",
+ "network": "911fe57e-1ddd-4151-9dc7-6b578ab357b1",
+ "object_name": "tapca33c645-5b",
+ "parent_id": "qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "show_in_tree": True,
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+}]
diff --git a/app/test/event_based_scan/test_data/event_payload_interface_delete.py b/app/test/event_based_scan/test_data/event_payload_interface_delete.py
new file mode 100644
index 0000000..5dbed2c
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_interface_delete.py
@@ -0,0 +1,350 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_INTERFACE_DELETE = {
+ 'message_id': 'da190e5f-127d-4e85-a813-bbdbbb35a2d0', '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_user_domain': None, '_context_resource_uuid': None, '_context_timestamp': '2016-11-07 23:41:04.169781',
+ '_unique_id': 'a4c4ef7a07c9431299047a59d4e0730c', 'event_type': 'router.interface.delete',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_request_id': 'req-e7d61486-2c0a-40cd-b346-1ec884b0e8d0', '_context_is_admin': True,
+ '_context_project_name': 'calipso-project', 'timestamp': '2016-11-07 23:41:09.769453',
+ '_context_auth_token': 'gAAAAABYIQ_M00kY8hGiB6zsD8BWn7b5x0aKIEv1HHQ3Ty0t5MAK68Lm7E6E0pDgJVqBSQsqZsNDqQkn4M0spYlz' +
+ 'WPTEdl3L4d-7ihNmWGOE76J4EtP9tl6nw22ZzdUhu4V8dVB5dqC3lhf61Ot9OsU7XRjp2zfVTb_Ip2yI2_auqUWZ' +
+ 'f6ryWdFPUZqbpJ3-jrVpUP1iXxlT',
+ '_context_roles': ['_member_', 'admin'], '_context_domain': None,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_project_domain': None,
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_user_name': 'admin',
+ 'publisher_id': 'network.node-251.cisco.com', '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_tenant_name': 'calipso-project', 'priority': 'INFO',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_show_deleted': False,
+ 'payload': {'router_interface': {'port_id': '1233445-75b6-4c05-9480-4bc648845c6f',
+ 'id': 'c57216ca-c1c4-430d-a045-32851ca879e3',
+ 'subnet_ids': ['6f6ef3b5-76c9-4f70-81e5-f3cc196db025'],
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'subnet_id': '6f6ef3b5-76c9-4f70-81e5-f3cc196db025'}},
+ '_context_read_only': False}
+
+NETWORK_DOC = {
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.12.0/24"
+ ],
+ "environment": ENV_CONFIG,
+ "id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0ae49" +
+ "73c8375ddf40-networks/55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "last_scanned": 0,
+ "mtu": 0,
+ "name": "please_connect",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/please_connect",
+ "network": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "object_name": "please_connect",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "calipso-project",
+ "provider:network_type": "vxlan",
+ "provider:physical_network": None,
+ "provider:segmentation_id": 23,
+ "router:external": False,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnet_ids": [
+ "6f6ef3b5-76c9-4f70-81e5-f3cc196db025"
+ ],
+ "subnets": {
+ "1234": {
+ "cidr": "172.16.12.0/24",
+ "network_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "allocation_pools": [
+ {
+ "start": "172.16.12.2",
+ "end": "172.16.12.254"
+ }
+ ],
+ "id": "6f6ef3b5-76c9-4f70-81e5-f3cc196db025",
+ "enable_dhcp": True,
+ "ipv6_address_mode": None,
+ "name": "1234",
+ "host_routes": [
+
+ ],
+ "ipv6_ra_mode": None,
+ "gateway_ip": "172.16.12.1",
+ "ip_version": 4,
+ "subnetpool_id": None,
+ "dns_nameservers": [
+
+ ],
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ },
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "network"
+}
+
+EVENT_PAYLOAD_REGION = {
+ 'RegionOne': {
+ 'object_name': 'RegionOne', 'id': 'RegionOne', 'name': 'RegionOne',
+ 'environment': ENV_CONFIG,
+ 'last_scanned': 0,
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne',
+ 'parent_id': ENV_CONFIG + '-regions', 'parent_type': 'regions_folder',
+ 'endpoints': {'nova': {'id': '274cbbd9fd6d4311b78e78dd3a1df51f',
+ 'adminURL': 'http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'compute',
+ 'publicURL': 'http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da'},
+ 'heat-cfn': {'id': '0f04ec6ed49f4940822161bf677bdfb2',
+ 'adminURL': 'http://192.168.0.2:8000/v1',
+ 'service_type': 'cloudformation',
+ 'publicURL': 'http://172.16.0.3:8000/v1',
+ 'internalURL': 'http://192.168.0.2:8000/v1'},
+ 'nova_ec2': {'id': '390dddc753cc4d378b489129d06c4b7d',
+ 'adminURL': 'http://192.168.0.2:8773/services/Admin',
+ 'service_type': 'ec2',
+ 'publicURL': 'http://172.16.0.3:8773/services/Cloud',
+ 'internalURL': 'http://192.168.0.2:8773/services/Cloud'},
+ 'glance': {'id': '475c6c77a94e4e63a5a0f0e767f697a8',
+ 'adminURL': 'http://192.168.0.2:9292',
+ 'service_type': 'image',
+ 'publicURL': 'http://172.16.0.3:9292',
+ 'internalURL': 'http://192.168.0.2:9292'},
+ 'swift': {'id': '12e78e06595f48339baebdb5d4309c70',
+ 'adminURL': 'http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'object-store',
+ 'publicURL': 'http://172.16.0.3:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da'},
+ 'swift_s3': {'id': '4f655c8f2bef46a0a7ba4a20bba53666',
+ 'adminURL': 'http://192.168.0.2:8080',
+ 'service_type': 's3',
+ 'publicURL': 'http://172.16.0.3:8080',
+ 'internalURL': 'http://192.168.0.2:8080'},
+ 'keystone': {'id': '404cceb349614eb39857742970408301',
+ 'adminURL': 'http://192.168.0.2:35357/v2.0',
+ 'service_type': 'identity',
+ 'publicURL': 'http://172.16.0.3:5000/v2.0',
+ 'internalURL': 'http://192.168.0.2:5000/v2.0'},
+ 'cinderv2': {'id': '2c30937688e944889db4a64fab6816e6',
+ 'adminURL': 'http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'volumev2',
+ 'publicURL': 'http://172.16.0.3:8776/v2/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da'},
+ 'novav3': {'id': '1df917160dfb4ce5b469764fde22b3ab',
+ 'adminURL': 'http://192.168.0.2:8774/v3',
+ 'service_type': 'computev3',
+ 'publicURL': 'http://172.16.0.3:8774/v3',
+ 'internalURL': 'http://192.168.0.2:8774/v3'},
+ 'ceilometer': {'id': '617177a3dcb64560a5a79ab0a91a7225',
+ 'adminURL': 'http://192.168.0.2:8777',
+ 'service_type': 'metering',
+ 'publicURL': 'http://172.16.0.3:8777',
+ 'internalURL': 'http://192.168.0.2:8777'},
+ 'neutron': {'id': '8dc28584da224c4b9671171ead3c982a',
+ 'adminURL': 'http://192.168.0.2:9696',
+ 'service_type': 'network',
+ 'publicURL': 'http://172.16.0.3:9696',
+ 'internalURL': 'http://192.168.0.2:9696'},
+ 'cinder': {'id': '05643f2cf9094265b432376571851841',
+ 'adminURL': 'http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'volume',
+ 'publicURL': 'http://172.16.0.3:8776/v1/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da'},
+ 'heat': {'id': '9e60268a5aaf422d9e42f0caab0a19b4',
+ 'adminURL': 'http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'orchestration',
+ 'publicURL': 'http://172.16.0.3:8004/v1/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da'}},
+ 'show_in_tree': True,
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne',
+ 'type': 'region'}}
+
+PORT_DOC = {
+ "admin_state_up": True,
+ "allowed_address_pairs": [
+
+ ],
+ "binding:host_id": "",
+ "binding:profile": {
+
+ },
+ "binding:vif_details": {
+
+ },
+ "binding:vif_type": "unbound",
+ "binding:vnic_type": "normal",
+ "device_id": "c57216ca-c1c4-430d-a045-32851ca879e3",
+ "device_owner": "network:router_interface",
+ "dns_assignment": [
+ {
+ "hostname": "host-172-16-10-1",
+ "ip_address": "172.16.10.1",
+ "fqdn": "host-172-16-10-1.openstacklocal."
+ }
+ ],
+ "dns_name": "",
+ "environment": ENV_CONFIG,
+ "extra_dhcp_opts": [
+
+ ],
+ "fixed_ips": [
+ {
+ "ip_address": "172.16.10.1",
+ "subnet_id": "6f6ef3b5-76c9-4f70-81e5-f3cc196db025"
+ }
+ ],
+ "id": "1233445-75b6-4c05-9480-4bc648845c6f",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "+/-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb" +
+ "79ff4a42b0ae4973c8375ddf40-networks/55550a69-24eb-47f5-a458-3aa086cc71c2/55550a69-24eb-" +
+ "47f5-a458-3aa086cc71c2-ports/1233445-75b6-4c05-9480-4bc648845c6f",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:13:b2:aa",
+ "master_parent_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "master_parent_type": "network",
+ "name": "fa:16:3e:13:b2:aa",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/test_interface/Ports/" +
+ "1233445-75b6-4c05-9480-4bc648845c6f",
+ "network_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "object_name": "1233445-75b6-4c05-9480-4bc648845c6f",
+ "parent_id": "55550a69-24eb-47f5-a458-3aa086cc71c2-ports",
+ "parent_text": "Ports",
+ "parent_type": "ports_folder",
+ "port_security_enabled": False,
+ "project": "calipso-project",
+ "security_groups": [
+
+ ],
+ "status": "DOWN",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "port"
+}
+
+ROUTER_DOCUMENT = {
+ "admin_state_up": True,
+ "enable_snat": 1,
+ "environment": ENV_CONFIG,
+ "gw_port_id": "e2f31c24-d0f9-499e-a8b1-883941543aa4",
+ "host": "node-251.cisco.com",
+ "id": "node-251.cisco.com-qrouter-c57216ca-c1c4-430d-a045-32851ca879e3",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-251.cisco.com/node-251.cisco.com-vservices/node-251.cisco.com-vservices-routers/node-251.cisco.com-qrouter-bde8" +
+ "7a5a-7968-4f3b-952c-e87681a96078",
+ "last_scanned": 0,
+ "local_service_id": "node-251.cisco.com-qrouter-c57216ca-c1c4-430d-a045-32851ca879e3",
+ "master_parent_id": "node-251.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "1234",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com/" +
+ "Vservices/Gateways/router-1234",
+ "network": [
+ "55550a69-24eb-47f5-a458-3aa086cc71c2"
+ ],
+ "object_name": "router-1234",
+ "parent_id": "node-251.cisco.com-vservices-routers",
+ "parent_text": "Gateways",
+ "parent_type": "vservice_routers_folder",
+ "service_type": "router",
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "vservice"
+}
+
+HOST = {
+ "config": {
+ "use_namespaces": True,
+ "handle_internal_only_routers": True,
+ "ex_gw_ports": 2,
+ "agent_mode": "legacy",
+ "log_agent_heartbeats": False,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "router_id": "",
+ "gateway_external_network_id": "",
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "routers": 2,
+ "interfaces": 4
+ },
+ "environment": ENV_CONFIG,
+ "host": "node-251.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-251.cisco.com",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones" +
+ "/internal/node-251.cisco.com",
+ "last_scanned": 0,
+ "name": "node-251.cisco.com",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com",
+ "object_name": "node-251.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-conductor": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:08.000000"
+ },
+ "nova-scheduler": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:38.000000"
+ },
+ "nova-cert": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:29.000000"
+ },
+ "nova-consoleauth": {
+ "available": True,
+ "active": True,
+ "updated_at": "2016-11-08T19:12:37.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+}
+
+VNIC_DOCS = [{
+ "IP Address": "172.16.10.2",
+ "IPv6 Address": "fe80::f816:3eff:fe96:5066/64",
+ "cidr": "172.16.10.0/25",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:96:50:66\ninet addr:172.16.10.2 Bcast:172.16.10.127 " +
+ "Mask:255.255.255.128\ninet6 addr: fe80::f816:3eff:fe96:5066/64 Scope:Link\nUP BROADCAST RUNNING " +
+ "MULTICAST MTU:1450 Metric:1\nRX packets:17 errors:0 dropped:2 overruns:0 frame:0\nTX packets:8 " +
+ "errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:1593 " +
+ "(1.5 KB) TX bytes:648 (648.0 B)\n",
+ "environment": ENV_CONFIG,
+ "host": "node-251.cisco.com",
+ "id": "tapca33c645-5b",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-251.cisco.com/node-251.cisco.com-vservices/node-251.cisco.com-vservices-dhcps/qdhcp-911fe57e" +
+ "-1ddd-4151-9dc7-6b578ab357b1/qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics/tapca33c645-5b",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:13:b2:aa",
+ "name": "tapca33c645-5b",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com/" +
+ "Vservices/DHCP servers/dhcp-test_interface/vNICs/tapca33c645-5b",
+ "netmask": "255.255.255.128",
+ "network": "911fe57e-1ddd-4151-9dc7-6b578ab357b1",
+ "object_name": "tapca33c645-5b",
+ "parent_id": "qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "show_in_tree": True,
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+}]
diff --git a/app/test/event_based_scan/test_data/event_payload_network_add.py b/app/test/event_based_scan/test_data/event_payload_network_add.py
new file mode 100644
index 0000000..9630965
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_network_add.py
@@ -0,0 +1,32 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+EVENT_PAYLOAD_NETWORK_ADD = {
+ '_context_request_id': 'req-d8593c49-8424-459b-9ac1-1fd8667310eb', '_context_project_domain': None,
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_project_name': 'calipso-project',
+ '_context_show_deleted': False, '_context_timestamp': '2016-09-30 17:45:01.738932', '_context_domain': None,
+ '_context_roles': ['_member_', 'admin'], '_context_is_admin': True, 'priority': 'INFO',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ 'message_id': '093e1ee0-87a7-4d40-9303-68d5eaf11f71', '_context_read_only': False,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_unique_id': '3dc7690856e14066902d861631236297', '_context_resource_uuid': None,
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_user_domain': None,
+ 'event_type': 'network.create.end', '_context_user_name': 'admin',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_auth_token': 'gAAAAABX7qQJkXEm4q2dRrVg4gjxYZ4iKWOFdkA4IVWXpDOiDtu_nwtAeSpTP3W0sEJiTjQXgxqCXrhCzi5cZ1edo6'
+ + 'DqEhND8TTtCqknIMwXcGGonUV0TkhKDOEnOgJhQLiV6JG-CtI4x0VnAp6muwankIGNChndH-gP0lw3bdIK29' +
+ 'aqDS4obeXGsYA3oLoORLubgPQjUpdO',
+ 'publisher_id': 'network.node-6.cisco.com', 'timestamp': '2016-09-30 17:45:02.125633',
+ '_context_tenant_name': 'calipso-project',
+ 'payload': {
+ 'network': {'provider:physical_network': None, 'router:external': False, 'shared': False,
+ 'id': 'a8226605-40d0-4111-93bd-11ffa5b2d1d7', 'provider:network_type': 'vxlan',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'mtu': 1400, 'subnets': [], 'status': 'ACTIVE',
+ 'provider:segmentation_id': 8, 'port_security_enabled': True, 'name': 'calipso-network-add',
+ 'admin_state_up': True}}}
diff --git a/app/test/event_based_scan/test_data/event_payload_network_delete.py b/app/test/event_based_scan/test_data/event_payload_network_delete.py
new file mode 100644
index 0000000..6884dd6
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_network_delete.py
@@ -0,0 +1,88 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+
+EVENT_PAYLOAD_NETWORK_DELETE = {
+ 'event_type': 'network.delete.end', 'priority': 'INFO', '_context_tenant_name': 'calipso-project',
+ '_context_domain': None, '_context_show_deleted': False, '_unique_id': 'e6f3a44575dd45ea891ec527335a55d7',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_read_only': False, '_context_timestamp': '2016-10-13 23:48:29.632205', '_context_project_domain': None,
+ '_context_roles': ['_member_', 'admin'], '_context_user_domain': None,
+ '_context_request_id': 'req-21307ef4-f4f7-4e8e-afaf-75dd04d71463',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'payload': {'network_id': '0bb0ba6c-6863-4121-ac89-93f81a9da2b0'}, '_context_user_name': 'admin',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_is_admin': True,
+ '_context_resource_uuid': None,
+ 'timestamp': '2016-10-13 23:48:31.609788', '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'message_id': '7b78b897-7a82-4aab-82a5-b1c431535dce', '_context_project_name': 'calipso-project',
+ '_context_auth_token': 'gAAAAABYAB0cVTm6fzL1S2q2lskw3z7FiEslh_amLhDmDEwQsm3M7L4omSjZ5qKacvgFTXS0HtpbCQfkZn8' +
+ 'BQK80qfbzaQdh05tW1gnboB_FR7vfsUZ1yKUzpDdAgfStDzj_SMWK6FGyZperukjp7Xhmxh91O6cxFvG1' +
+ '0qZmxwtJoKyuW0pCM1593rTsj1Lh6zOIo2iaoC1a',
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', 'publisher_id': 'network.node-6.cisco.com'}
+
+
+EVENT_PAYLOAD_NETWORK = {
+ "admin_state_up" : True,
+ "cidrs" : [
+ "172.16.9.0/24"
+ ],
+ "environment" : ENV_CONFIG,
+ "id" : '0bb0ba6c-6863-4121-ac89-93f81a9da2b0',
+ "id_path" : '/%s/%s-projects/' % (ENV_CONFIG, ENV_CONFIG) +'75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b' +
+ '0ae4973c8375ddf40-networks/0bb0ba6c-6863-4121-ac89-93f81a9da2b0' ,
+ "last_scanned" : 0,
+ "mtu" : 1400,
+ "name" : "testnetwork",
+ "name_path" : "/"+ENV_CONFIG+"/Projects/calipso-project/Networks/testnetwork",
+ "network" : "0bb0ba6c-6863-4121-ac89-93f81a9da2b0",
+ "object_name" : "testnetwork",
+ "parent_id" : "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text" : "Networks",
+ "parent_type" : "networks_folder",
+ "port_security_enabled" : True,
+ "project" : "calipso-project",
+ "provider:network_type" : "vxlan",
+ "provider:physical_network" : None,
+ "provider:segmentation_id" : 107,
+ "router:external" : False,
+ "shared" : False,
+ "show_in_tree" : True,
+ "status" : "ACTIVE",
+ "subnets" : {
+ "testabc" : {
+ "dns_nameservers" : [
+
+ ],
+ "enable_dhcp" : False,
+ "host_routes" : [
+
+ ],
+ "cidr" : "172.16.9.0/24",
+ "ip_version" : 4,
+ "id" : "7a1be27e-4aae-43ef-b3c0-7231a41625b8",
+ "subnetpool_id" : None,
+ "ipv6_ra_mode" : None,
+ "ipv6_address_mode" : None,
+ "network_id" : "0bb0ba6c-6863-4121-ac89-93f81a9da2b0",
+ "tenant_id" : "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "name" : "testabc",
+ "allocation_pools" : [
+ {
+ "end" : "172.16.9.254",
+ "start" : "172.16.9.2"
+ }
+ ],
+ "gateway_ip" : "172.16.9.1"
+ }
+ },
+ "tenant_id" : "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type" : "network"
+} \ No newline at end of file
diff --git a/app/test/event_based_scan/test_data/event_payload_network_update.py b/app/test/event_based_scan/test_data/event_payload_network_update.py
new file mode 100644
index 0000000..3485cd1
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_network_update.py
@@ -0,0 +1,65 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_NETWORK_UPDATE = {
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ 'priority': 'INFO',
+ '_context_auth_token': 'gAAAAABYBrNJA6Io1infkUKquvCpC1bAWOCRxKE-8YQ71qLJhli200beztKmlY5ToBHSqFyPvoadkVKjA740jF' +
+ 'bqeY-YtezMHhJAe-t_VyRJQ46IWAv8nPYvWRd_lmgtHrvBeId8NIPCZkhoAEmj5GwcZUZgnFYEhVlUliNO6IfV' +
+ 'Oxcb17Z_1MKfdrfu1AtgD5hWb61w1F6x',
+ '_context_user_name': 'admin', '_context_project_name': 'calipso-project', '_context_domain': None,
+ '_unique_id': 'd1a96723db9341dca6f0d5fb9620f548', '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'message_id': '6b99d060-9cd6-4c14-8a0a-cbfc5c50d122', 'timestamp': '2016-10-18 23:47:31.636433',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_resource_uuid': None, '_context_request_id': 'req-b33cbd49-7af9-4c64-bcfb-782fcd400a5e',
+ 'publisher_id': 'network.node-6.cisco.com', 'payload': {
+ 'network': {'provider:network_type': 'vxlan', 'port_security_enabled': True, 'status': 'ACTIVE',
+ 'id': '8673c48a-f137-4497-b25d-08b7b218fd17', 'shared': False, 'router:external': False,
+ 'subnets': ['fcfa62ec-5ae7-46ce-9259-5f30de7af858'], 'admin_state_up': True,
+ 'provider:segmentation_id': 52, 'provider:physical_network': None, 'name': '24',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'mtu': 1400}}, 'event_type': 'network.update.end',
+ '_context_roles': ['_member_', 'admin'], '_context_project_domain': None, '_context_is_admin': True,
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_show_deleted': False, '_context_user_domain': None,
+ '_context_read_only': False, '_context_timestamp': '2016-10-18 23:47:20.629297',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_tenant_name': 'calipso-project'}
+
+
+NETWORK_DOCUMENT = {
+ "admin_state_up" : True,
+ "cidrs" : [
+ "172.16.4.0/24"
+ ],
+ "environment" : ENV_CONFIG,
+ "id" : "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "id_path" : '/%s/%s-projects/' % (ENV_CONFIG, ENV_CONFIG) +'75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b' +
+ '0ae4973c8375ddf40-networks/8673c48a-f137-4497-b25d-08b7b218fd17',
+ "last_scanned" : 0,
+ "mtu" : 1400,
+ "name" : "calipso-met4",
+ "name_path" : "/"+ENV_CONFIG+"/Projects/calipso-project/Networks/calipso-met4",
+ "network" : "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "object_name" : "calipso-met4",
+ "parent_id" : "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text" : "Networks",
+ "parent_type" : "networks_folder",
+ "port_security_enabled" : True,
+ "project" : "calipso-project",
+ "provider:network_type" : "vxlan",
+ "provider:physical_network" : None,
+ "provider:segmentation_id" : 0,
+ "router:external" : False,
+ "shared" : False,
+ "show_in_tree" : True,
+ "status" : "ACTIVE",
+ "subnets" : {},
+ "tenant_id" : "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type" : "network"
+} \ No newline at end of file
diff --git a/app/test/event_based_scan/test_data/event_payload_port_add.py b/app/test/event_based_scan/test_data/event_payload_port_add.py
new file mode 100644
index 0000000..92f6d2f
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_port_add.py
@@ -0,0 +1,314 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_PORT_INSTANCE_ADD = {
+ '_context_user_id': '73638a2687534f9794cd8057ba860637', 'payload': {
+ 'port': {'port_security_enabled': True, 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'binding:vif_type': 'ovs',
+ 'mac_address': 'fa:16:3e:04:cd:ab',
+ 'fixed_ips': [{'subnet_id': '9a9c1848-ea23-4c5d-8c40-ae1def4c2de3', 'ip_address': '172.16.13.6'}],
+ 'security_groups': ['2dd5c169-1ff7-40e5-ad96-18924b6d23f1'], 'allowed_address_pairs': [],
+ 'binding:host_id': 'node-223.cisco.com', 'dns_name': '', 'status': 'DOWN',
+ 'id': '1233445-75b6-4c05-9480-4bc648845c6f', 'binding:profile': {}, 'admin_state_up': True,
+ 'device_owner': 'compute:calipso-zone', 'device_id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'network_id': '55550a69-24eb-47f5-a458-3aa086cc71c2', 'name': '',
+ 'binding:vif_details': {'ovs_hybrid_plug': True, 'port_filter': True}, 'extra_dhcp_opts': [],
+ 'binding:vnic_type': 'normal'}}, '_context_project_domain': None, 'event_type': 'port.create.end',
+ 'message_id': '2e0da8dc-6d2d-4bde-9e52-c43ec4687864', 'publisher_id': 'network.node-6.cisco.com',
+ '_context_domain': None, '_context_tenant_name': 'services', '_context_tenant': 'a83c8b0d2df24170a7c54f09f824230e',
+ '_context_project_name': 'services', '_context_user': '73638a2687534f9794cd8057ba860637',
+ '_context_user_name': 'neutron', 'priority': 'INFO', '_context_timestamp': '2016-10-24 21:29:52.127098',
+ '_context_read_only': False, '_context_roles': ['admin'], '_context_is_admin': True, '_context_show_deleted': False,
+ '_context_user_domain': None,
+ '_context_auth_token': 'gAAAAABYDnRG3mhPMwyF17iUiIT4nYjtcSktNmmCKlMrUtmpHYsJWl44xU-boIaf4ChWcBsTjl6jOk6Msu7l17As' +
+ '1Y9vFc1rlmKMl86Eknqp0P22RV_Xr6SIobsl6Axl2Z_w-AB1cZ4pSsY4uscxeJdVkoxRb0aC9B7gllrvAgrfO9O' +
+ 'GDqw2ILA',
+ '_context_tenant_id': 'a83c8b0d2df24170a7c54f09f824230e', '_context_resource_uuid': None,
+ '_context_request_id': 'req-3d6810d9-bee9-41b5-a224-7e9641689cc8', '_unique_id': 'b4f1ffae88b342c09658d9ed2829670c',
+ 'timestamp': '2016-10-24 21:29:56.383789', '_context_project_id': 'a83c8b0d2df24170a7c54f09f824230e',
+ '_context_user_identity': '73638a2687534f9794cd8057ba860637 a83c8b0d2df24170a7c54f09f824230e - - -'}
+
+NETWORK_DOC = {
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.12.0/24"
+ ],
+ "environment": ENV_CONFIG,
+ "id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0ae" +
+ "4973c8375ddf40-networks/55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "last_scanned": 0,
+ "mtu": 0,
+ "name": "please_connect",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/please_connect",
+ "network": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "object_name": "please_connect",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "calipso-project",
+ "provider:network_type": "vxlan",
+ "provider:physical_network": None,
+ "provider:segmentation_id": 23,
+ "router:external": False,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnet_ids": [
+ "6f6ef3b5-76c9-4f70-81e5-f3cc196db025"
+ ],
+ "subnets": {
+ "1234": {
+ "cidr": "172.16.12.0/24",
+ "network_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "allocation_pools": [
+ {
+ "start": "172.16.12.2",
+ "end": "172.16.12.254"
+ }
+ ],
+ "id": "6f6ef3b5-76c9-4f70-81e5-f3cc196db025",
+ "enable_dhcp": True,
+ "ipv6_address_mode": None,
+ "name": "1234",
+ "host_routes": [
+
+ ],
+ "ipv6_ra_mode": None,
+ "gateway_ip": "172.16.12.1",
+ "ip_version": 4,
+ "subnetpool_id": None,
+ "dns_nameservers": [
+
+ ],
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ },
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "network"
+}
+
+INSTANCE_DOC = {
+ "environment": ENV_CONFIG,
+ "id": "b2bda4bf-1259-4d60-99ab-85ab4d5014a8",
+ "type": "instance",
+ "uuid": "b2bda4bf-1259-4d60-99ab-85ab4d5014a8",
+ "network": [
+ "a09455d9-399a-4193-9cb4-95e9d8e9a560"
+ ],
+ "local_name": "instance-00000002",
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne/Availability Zones' +
+ '/calipso-zone/node-223.cisco.com/Instances/name-change',
+ 'id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne/RegionOne-availability_zones/calipso-zone' +
+ '/node-223.cisco.com/node-223.cisco.com-instances/27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ "name": "name-change",
+ "network_info": [
+ {
+ "qbg_params": None,
+ "id": "1233445-75b6-4c05-9480-4bc648845c6f",
+ "network": {
+ "bridge": "br-int",
+ "meta": {
+ "injected": False,
+ "tenant_id": "a3efb05cd0484bf0b600e45dab09276d"
+ },
+ "id": "a09455d9-399a-4193-9cb4-95e9d8e9a560",
+ "subnets": [
+ {
+ "gateway": {
+ "meta": {
+
+ },
+ "type": "gateway",
+ "version": 4,
+ "address": "172.16.50.254"
+ },
+ "version": 4,
+ "dns": [
+
+ ],
+ "cidr": "172.16.50.0/24",
+ "routes": [
+
+ ],
+ "meta": {
+ "dhcp_server": "172.16.50.1"
+ },
+ "ips": [
+ {
+ "floating_ips": [
+
+ ],
+ "meta": {
+
+ },
+ "type": "fixed",
+ "version": 4,
+ "address": "172.16.50.3"
+ }
+ ]
+ }
+ ],
+ "label": "calipso-network"
+ },
+ "active": True,
+ "address": "fa:16:3e:04:cd:ab",
+ "vnic_type": "normal",
+ "meta": {
+ },
+ "ovs_interfaceid": "1233445-75b6-4c05-9480-4bc648845c6f",
+ "type": "ovs",
+ "devname": "tapa9a8fa24-11",
+ }
+ ],
+ "host": "node-223.cisco.com",
+ "project_id": "a3efb05cd0484bf0b600e45dab09276d",
+ "object_name": "libertyDD",
+ "parent_id": "node-223.cisco.com-instances",
+ "parent_type": "instances_folder",
+ "projects": [
+ "project-calipso"
+ ],
+ "mac_address": "fa:16:3e:04:cd:ab"
+}
+
+INSTANCES_ROOT = {
+ "create_object": True,
+ "environment": ENV_CONFIG,
+ "id": "node-223.cisco.com-instances",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones" +
+ "/calipso-zone/node-223.cisco.com/node-223.cisco.com-instances",
+ "name": "Instances",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/calipso-zone/node-223.cisco.com/Instances",
+ "object_name": "Instances",
+ "parent_id": "node-223.cisco.com",
+ "parent_type": "host",
+ "show_in_tree": True,
+ "text": "Instances",
+ "type": "instances_folder"
+}
+
+INSTANCE_DOCS = [
+ {
+ "environment": ENV_CONFIG,
+ "type": "instance",
+ "uuid": "b2bda4bf-1259-4d60-99ab-85ab4d5014a8",
+ "network": [
+ "a09455d9-399a-4193-9cb4-95e9d8e9a560"
+ ],
+ "local_name": "instance-00000002",
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne/Availability Zones' +
+ '/calipso-zone/node-223.cisco.com/Instances/name-change',
+ 'id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne/RegionOne-availability_zones/calipso-zone' +
+ '/node-223.cisco.com/node-223.cisco.com-instances/27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ "name": "name-change",
+ "network_info": [
+ {
+ "qbg_params": None,
+ "id": "2233445-75b6-4c05-9480-4bc648845c6f",
+ "network": {
+ "bridge": "br-int",
+ "meta": {
+ "injected": False,
+ "tenant_id": "a3efb05cd0484bf0b600e45dab09276d"
+ },
+ "id": "a09455d9-399a-4193-9cb4-95e9d8e9a560",
+ "subnets": [
+ {
+ "gateway": {
+ "meta": {
+
+ },
+ "type": "gateway",
+ "version": 4,
+ "address": "172.16.50.254"
+ },
+ "version": 4,
+ "dns": [
+
+ ],
+ "cidr": "172.16.50.0/24",
+ "routes": [
+
+ ],
+ "meta": {
+ "dhcp_server": "172.16.50.1"
+ },
+ "ips": [
+ {
+ "floating_ips": [
+
+ ],
+ "meta": {
+
+ },
+ "type": "fixed",
+ "version": 4,
+ "address": "172.16.50.3"
+ }
+ ]
+ }
+ ],
+ "label": "calipso-network"
+ },
+ "active": True,
+ "address": "fa:16:3e:04:cd:ab",
+ "vnic_type": "normal",
+ "meta": {
+ },
+ "ovs_interfaceid": "2233445-75b6-4c05-9480-4bc648845c6f",
+ "type": "ovs",
+ "devname": "tapa9a8fa24-12",
+ }
+ ],
+ "host": "node-223.cisco.com",
+ "project_id": "a3efb05cd0484bf0b600e45dab09276d",
+ "object_name": "libertyDD",
+ "parent_id": "node-223.cisco.com-instances",
+ "parent_type": "instances_folder",
+ "projects": [
+ "project-calipso"
+ ],
+ "mac_address": "fa:16:3e:04:cd:ab"
+ }
+]
+
+VNIC_DOCS = [{
+ "IP Address": "172.16.10.2",
+ "IPv6 Address": "fe80::f816:3eff:fe96:5066/64",
+ "cidr": "172.16.10.0/25",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:96:50:66\ninet addr:172.16.10.2 Bcast:172.16.10.127 " +
+ "Mask:255.255.255.128\ninet6 addr: fe80::f816:3eff:fe96:5066/64 Scope:Link\nUP BROADCAST RUNNING " +
+ "MULTICAST MTU:1450 Metric:1\nRX packets:17 errors:0 dropped:2 overruns:0 frame:0\nTX packets:8 " +
+ "errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:1593 " +
+ "(1.5 KB) TX bytes:648 (648.0 B)\n",
+ "host": "node-251.cisco.com",
+ "id": "tapca33c645-5b",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-251.cisco.com/node-251.cisco.com-vservices/node-251.cisco.com-vservices-dhcps/qdhcp-911fe57e" +
+ "-1ddd-4151-9dc7-6b578ab357b1/qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics/tapca33c645-5b",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:04:cd:ab",
+ "name": "tapca33c645-5b",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com/" +
+ "Vservices/DHCP servers/dhcp-test_interface/vNICs/tapca33c645-5b",
+ "netmask": "255.255.255.128",
+ "network": "911fe57e-1ddd-4151-9dc7-6b578ab357b1",
+ "object_name": "tapca33c645-5b",
+ "parent_id": "qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "show_in_tree": True,
+ "vnic_type": "instance_vnic"
+}]
diff --git a/app/test/event_based_scan/test_data/event_payload_port_delete.py b/app/test/event_based_scan/test_data/event_payload_port_delete.py
new file mode 100644
index 0000000..afbba32
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_port_delete.py
@@ -0,0 +1,290 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_PORT_DELETE = {
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_tenant_name': 'calipso-project',
+ '_context_project_name': 'calipso-project', '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_auth_token': 'gAAAAABYIR4eeMzyZ6IWHjWSK9kmr-p4hxRhm5LtDp--kiu5v5MzpnShwkZAbFTkIBR0fC2iaBurXlAvI0pE' +
+ 'myBRpAuxWFsM5rbsiFlo_qpuo_dqIGe6_R7J-MDIGnLCl4T3z3Rb4asZKksXRhP5brkJF1-LdqAXJJ55sgQ' +
+ 'aH-22H9g9Wxhziz5YaoshWskJYhb_geTeqPsa',
+ '_context_show_deleted': False, '_context_read_only': False, '_context_is_admin': True,
+ '_context_timestamp': '2016-11-08 00:58:07.248644',
+ 'payload': {'port_id': '2233445-55b6-4c05-9480-4bc648845c6f'},
+ 'timestamp': '2016-11-08 00:58:07.294731', '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ 'event_type': 'port.delete.start', '_unique_id': '83a98a31743c4c11aa1d1787037f6683',
+ '_context_request_id': 'req-51f0aeba-2648-436f-9505-0c5efb259146', 'publisher_id': 'network.node-6.cisco.com',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_domain': None, '_context_user_domain': None, 'priority': 'INFO', '_context_user_name': 'admin',
+ '_context_roles': ['_member_', 'admin'], 'message_id': 'ce1e3e9c-e2ef-47e2-99e1-0b6c69e5eeca',
+ '_context_resource_uuid': None, '_context_project_domain': None,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40'}
+
+PORT_DOC = {
+ "admin_state_up": True,
+ "allowed_address_pairs": [
+
+ ],
+ "binding:host_id": "",
+ "binding:profile": {
+
+ },
+ "binding:vif_details": {
+
+ },
+ "binding:vif_type": "unbound",
+ "binding:vnic_type": "normal",
+ "device_id": "c57216ca-c1c4-430d-a045-32851ca879e3",
+ "device_owner": "compute:nova",
+ "dns_assignment": [
+ {
+ "hostname": "host-172-16-10-1",
+ "ip_address": "172.16.10.1",
+ "fqdn": "host-172-16-10-1.openstacklocal."
+ }
+ ],
+ "dns_name": "",
+ "environment": ENV_CONFIG,
+ "extra_dhcp_opts": [
+
+ ],
+ "fixed_ips": [
+ {
+ "ip_address": "172.16.10.1",
+ "subnet_id": "6f6ef3b5-76c9-4f70-81e5-f3cc196db025"
+ }
+ ],
+ "id": "2233445-55b6-4c05-9480-4bc648845c6f",
+ "id_path": ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0ae4973c837" +
+ "5ddf40-networks/55550a69-24eb-47f5-a458-3aa086cc71c2/55550a69-24eb-47f5-a458-3aa086cc71c2-ports" +
+ "/2233445-55b6-4c05-9480-4bc648845c6f",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:13:b2:aa",
+ "master_parent_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "master_parent_type": "network",
+ "name": "fa:16:3e:13:b2:aa",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/test_interface/Ports/" +
+ "2233445-55b6-4c05-9480-4bc648845c6f",
+ "network_id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "object_name": "2233445-55b6-4c05-9480-4bc648845c6f",
+ "parent_id": "55550a69-24eb-47f5-a458-3aa086cc71c2-ports",
+ "parent_text": "Ports",
+ "parent_type": "ports_folder",
+ "port_security_enabled": False,
+ "project": "calipso-project",
+ "security_groups": [
+
+ ],
+ "status": "DOWN",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "port"
+}
+
+VNIC_DOCS = [{
+ "IP Address": "172.16.10.2",
+ "IPv6 Address": "fe80::f816:3eff:fe96:5066/64",
+ "cidr": "172.16.10.0/25",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:96:50:66\ninet addr:172.16.10.2 Bcast:172.16.10.127 " +
+ "Mask:255.255.255.128\ninet6 addr: fe80::f816:3eff:fe96:5066/64 Scope:Link\nUP BROADCAST RUNNING " +
+ "MULTICAST MTU:1450 Metric:1\nRX packets:17 errors:0 dropped:2 overruns:0 frame:0\nTX packets:8 " +
+ "errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:1593 " +
+ "(1.5 KB) TX bytes:648 (648.0 B)\n",
+ "environment": ENV_CONFIG,
+ "host": "node-251.cisco.com",
+ "id": "tapca33c645-5b",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-251.cisco.com/node-251.cisco.com-vservices/node-251.cisco.com-vservices-dhcps/qdhcp-911fe57e-" +
+ "1ddd-4151-9dc7-6b578ab357b1/qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics/tapca33c645-5b",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:13:b2:aa",
+ "name": "tapca33c645-5b",
+ "name_path": "/"+ENV_CONFIG+"/Regions/RegionOne/Availability Zones/internal/node-251.cisco.com/" +
+ "Vservices/DHCP servers/dhcp-test_interface/vNICs/tapca33c645-5b",
+ "netmask": "255.255.255.128",
+ "network": "911fe57e-1ddd-4151-9dc7-6b578ab357b1",
+ "object_name": "tapca33c645-5b",
+ "parent_id": "qdhcp-911fe57e-1ddd-4151-9dc7-6b578ab357b1-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "show_in_tree": True,
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+}]
+
+INSTANCE_DOC = {
+ "environment": ENV_CONFIG,
+ "id": "b2bda4bf-1259-4d60-99ab-85ab4d5014a8",
+ "type": "instance",
+ "uuid": "b2bda4bf-1259-4d60-99ab-85ab4d5014a8",
+ "network": [
+ "55550a69-24eb-47f5-a458-3aa086cc71c2"
+ ],
+ "local_name": "instance-00000002",
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne/Availability Zones' +
+ '/calipso-zone/node-223.cisco.com/Instances/name-change',
+ 'id': '27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne/RegionOne-availability_zones/calipso-zone' +
+ '/node-223.cisco.com/node-223.cisco.com-instances/27a87908-bc1b-45cc-9238-09ad1ae686a7',
+ "name": "name-change",
+ "network_info": [
+ {
+ "qbg_params": None,
+ "id": "2233445-55b6-4c05-9480-4bc648845c6f",
+ "network": {
+ "bridge": "br-int",
+ "meta": {
+ "injected": False,
+ "tenant_id": "a3efb05cd0484bf0b600e45dab09276d"
+ },
+ "id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "subnets": [
+ {
+ "gateway": {
+ "meta": {
+
+ },
+ "type": "gateway",
+ "version": 4,
+ "address": "172.16.50.254"
+ },
+ "version": 4,
+ "dns": [
+
+ ],
+ "cidr": "172.16.50.0/24",
+ "routes": [
+
+ ],
+ "meta": {
+ "dhcp_server": "172.16.50.1"
+ },
+ "ips": [
+ {
+ "floating_ips": [
+
+ ],
+ "meta": {
+
+ },
+ "type": "fixed",
+ "version": 4,
+ "address": "172.16.50.3"
+ }
+ ]
+ }
+ ],
+ "label": "calipso-network"
+ },
+ "active": True,
+ "address": "fa:16:3e:04:ab:cd",
+ "vnic_type": "normal",
+ "meta": {
+ },
+ "ovs_interfaceid": "2233445-55b6-4c05-9480-4bc648845c6f",
+ "type": "ovs",
+ "devname": "tapa9a8fa24-11",
+ }
+ ],
+ "host": "node-223.cisco.com",
+ "project_id": "a3efb05cd0484bf0b600e45dab09276d",
+ "object_name": "libertyDD",
+ "parent_id": "node-223.cisco.com-instances",
+ "parent_type": "instances_folder",
+ "projects": [
+ "project-calipso"
+ ],
+ "mac_address": "fa:16:3e:13:b2:aa"
+}
+
+INSTANCE_DOCS = [
+ {
+ "environment": ENV_CONFIG,
+ "type": "instance",
+ "uuid": "b2bda4bf-1259-4d60-99ab-85ab4d5014a8",
+ "network": [
+ "55550a69-24eb-47f5-a458-3aa086cc71c2"
+ ],
+ "local_name": "instance-00000002",
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne/Availability Zones' +
+ '/calipso-zone/node-223.cisco.com/Instances/name-change',
+ 'id': 'c57216ca-c1c4-430d-a045-32851ca879e3',
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne/RegionOne-availability_zones/calipso-zone' +
+ '/node-223.cisco.com/node-223.cisco.com-instances/c57216ca-c1c4-430d-a045-32851ca879e3',
+ "name": "name-change",
+ "network_info": [
+ {
+ "qbg_params": None,
+ "id": "2233445-55b6-4c05-9480-4bc648845c6f",
+ "network": {
+ "bridge": "br-int",
+ "meta": {
+ "injected": False,
+ "tenant_id": "a3efb05cd0484bf0b600e45dab09276d"
+ },
+ "id": "55550a69-24eb-47f5-a458-3aa086cc71c2",
+ "subnets": [
+ {
+ "gateway": {
+ "meta": {
+
+ },
+ "type": "gateway",
+ "version": 4,
+ "address": "172.16.50.254"
+ },
+ "version": 4,
+ "dns": [
+
+ ],
+ "cidr": "172.16.50.0/24",
+ "routes": [
+
+ ],
+ "meta": {
+ "dhcp_server": "172.16.50.1"
+ },
+ "ips": [
+ {
+ "floating_ips": [
+
+ ],
+ "meta": {
+
+ },
+ "type": "fixed",
+ "version": 4,
+ "address": "172.16.50.3"
+ }
+ ]
+ }
+ ],
+ "label": "calipso-network"
+ },
+ "active": True,
+ "address": "fa:16:3e:04:ab:cd",
+ "vnic_type": "normal",
+ "meta": {
+ },
+ "ovs_interfaceid": "2233445-75b6-4c05-9480-4bc648845c6f",
+ "type": "ovs",
+ "devname": "tapa9a8fa24-12",
+ }
+ ],
+ "host": "node-223.cisco.com",
+ "project_id": "a3efb05cd0484bf0b600e45dab09276d",
+ "object_name": "libertyDD",
+ "parent_id": "node-223.cisco.com-instances",
+ "parent_type": "instances_folder",
+ "projects": [
+ "project-calipso"
+ ],
+ }
+] \ No newline at end of file
diff --git a/app/test/event_based_scan/test_data/event_payload_port_update.py b/app/test/event_based_scan/test_data/event_payload_port_update.py
new file mode 100644
index 0000000..90befbf
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_port_update.py
@@ -0,0 +1,103 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_PORT_UPDATE = {
+ '_context_timestamp': '2016-10-25 21:27:05.591848', '_context_user_name': 'admin',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_name': 'calipso-project', '_context_resource_uuid': None,
+ 'priority': 'INFO', '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_domain': None, '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40', 'event_type': 'port.update.end',
+ '_context_project_domain': None, '_context_show_deleted': False,
+ '_context_request_id': 'req-5c502a18-cf79-4903-85c0-84eeab525378',
+ '_context_roles': ['_member_', 'admin'],
+ 'message_id': 'ee8e493e-1134-4077-bb0a-db9d28b625dd', 'payload': {'port': {
+ 'dns_assignment': [
+ {'ip_address': '172.16.4.2', 'fqdn': 'host-172-16-4-2.openstacklocal.', 'hostname': 'host-172-16-4-2'}],
+ 'mac_address': 'fa:16:3e:d7:c5:16', 'security_groups': [], 'admin_state_up': True, 'dns_name': '',
+ 'allowed_address_pairs': [], 'binding:profile': {},
+ 'binding:vif_details': {'port_filter': True, 'ovs_hybrid_plug': True}, 'port_security_enabled': False,
+ 'device_id': 'dhcp7a15cee0-2af1-5441-b1dc-94897ef4dee9-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe',
+ 'id': '16620a58-c48c-4195-b9c1-779a8ba2e6f8',
+ 'fixed_ips': [{'subnet_id': 'f68b9dd3-4cb5-46aa-96b1-f9c8a7abc3aa', 'ip_address': '172.16.4.2'}],
+ 'name': 'test',
+ 'binding:vnic_type': 'normal', 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'extra_dhcp_opts': [],
+ 'network_id': 'b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe', 'binding:vif_type': 'ovs',
+ 'binding:host_id': 'node-6.cisco.com', 'status': 'ACTIVE', 'device_owner': 'network:dhcp'}},
+ 'timestamp': '2016-10-25 21:27:06.281892',
+ '_unique_id': '964361cb7a434daf9fa6452507133fe5',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_user_domain': None,
+ '_context_auth_token': 'gAAAAABYD8zsy7c8LhL2SoZTzmK-YpUMFBJHare_RA7_4E94zqj328sC0cETsFAoWoBY' +
+ '6X8ZvjBQg--5UCqgj7iUE-zfIQwZLzXbl46MP1Fg5ZKCUtdCCPN5yqXxGA-ebYlBB_G' +
+ 'If0LUo1YXCKe3GacmfFNC-k0T_B1p340stgLdpW7r0g1jvTDleqK7NWNrnCniZHrgGiLw',
+ '_context_is_admin': True, '_context_read_only': False,
+ '_context_project_name': 'calipso-project',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ 'publisher_id': 'network.node-6.cisco.com'}
+
+PORT_DOCUMENT = {
+ "admin_state_up": True,
+ "allowed_address_pairs": [
+
+ ],
+ "binding:host_id": "node-6.cisco.com",
+ "binding:profile": {
+
+ },
+ "binding:vif_details": {
+ "port_filter": True,
+ "ovs_hybrid_plug": True
+ },
+ "binding:vif_type": "ovs",
+ "binding:vnic_type": "normal",
+ "device_id": "dhcp7a15cee0-2af1-5441-b1dc-94897ef4dee9-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "device_owner": "network:dhcp",
+ "dns_assignment": [
+ {
+ "hostname": "host-172-16-4-2",
+ "fqdn": "host-172-16-4-2.openstacklocal.",
+ "ip_address": "172.16.4.2"
+ }
+ ],
+ "dns_name": "",
+ "environment": ENV_CONFIG,
+ "extra_dhcp_opts": [
+
+ ],
+ "fixed_ips": [
+ {
+ "subnet_id": "f68b9dd3-4cb5-46aa-96b1-f9c8a7abc3aa",
+ "ip_address": "172.16.4.2"
+ }
+ ],
+ "id": "16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb" +
+ "79ff4a42b0ae4973c8375ddf40-networks/b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe/b6fd5175-4b22" +
+ "-4256-9b1a-9fc4b9dce1fe-ports/16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:d7:c5:16",
+ "name": "123",
+ "name_path": "/"+ENV_CONFIG+"/Projects/calipso-project/Networks/calipso-met4/Ports/fa:16:3e:d7:c5:16",
+ "network_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "object_name": "fa:16:3e:d7:c5:16",
+ "parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe-ports",
+ "parent_text": "Ports",
+ "parent_type": "ports_folder",
+ "port_security_enabled": False,
+ "project": "calipso-project",
+ "security_groups": [
+
+ ],
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "port"
+}
diff --git a/app/test/event_based_scan/test_data/event_payload_router_add.py b/app/test/event_based_scan/test_data/event_payload_router_add.py
new file mode 100644
index 0000000..153538d
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_router_add.py
@@ -0,0 +1,176 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import datetime
+
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_ROUTER_ADD = {
+ '_context_show_deleted': False, '_context_domain': None,
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ 'message_id': '05682485-9283-4cef-aae5-0bc1e86ed14d',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_read_only': False,
+ '_context_user_domain': None, '_unique_id': '40f10fd246814669b61d906fd71be301',
+ '_context_auth_token': 'gAAAAABYE58-bIhpHKOyCNnav0czsBonPJbJJPxtkTFHT_gJ-sVPPO1xCldKOoJoJ58M5egmK0' +
+ 'tsCOiH9N6u-2h08rH84nrnE6YUoLJM_SWyJlbYDzH7rJyHYPBVE1aYkzMceiy7Jr33G4k6cGZQ' +
+ '7UzAaZRrGLxMMFddvNZa47dVPZsg1oJpdIVVcoaRHf4hPM8lj1qSn6WG',
+ 'event_type': 'router.create.end', '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'priority': 'INFO', '_context_roles': ['_member_', 'admin'],
+ '_context_project_name': 'calipso-project',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_request_id': 'req-a543a2e4-3160-4e98-b1b8-21a876fff205',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'timestamp': '2016-10-28 19:00:36.600958',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_name': 'calipso-project', 'payload': {
+ 'router': {'name': 'test-router-add',
+ 'external_gateway_info': {
+ 'enable_snat': True,
+ 'external_fixed_ips': [{
+ 'ip_address': '172.16.0.137',
+ 'subnet_id': 'a5336853-cbc0-49e8-8401-a093e8bab7bb'}],
+ 'network_id': 'c64adb76-ad9d-4605-9f5e-123456781234'},
+ 'admin_state_up': True,
+ 'distributed': False,
+ 'routes': [], 'ha': False,
+ 'id': 'c485d5f4-dfec-430f-8ad8-409c7034b46d',
+ 'status': 'ACTIVE',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40'}},
+ '_context_timestamp': '2016-10-28 19:00:34.395521', '_context_project_domain': None,
+ 'publisher_id': 'network.node-250.cisco.com', '_context_is_admin': True,
+ '_context_user_name': 'admin', '_context_resource_uuid': None}
+
+ROUTER_DOCUMENT = {'host': 'node-250.cisco.com', 'service_type': 'router', 'name': 'router-test-router-add',
+ 'id': 'node-250.cisco.com-qrouter-c485d5f4-dfec-430f-8ad8-409c7034b46d',
+ 'local_service_id': 'node-250.cisco.com-qrouter-c485d5f4-dfec-430f-8ad8-409c7034b46d',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'status': 'ACTIVE',
+ 'master_parent_type': 'vservices_folder',
+ 'admin_state_up': 1, 'parent_type': 'vservice_routers_folder', 'enable_snat': 1,
+ 'parent_text': 'Gateways',
+ 'gw_port_id': 'e2f31c24-d0f9-499e-a8b1-883941543aa4',
+ 'master_parent_id': 'node-250.cisco.com-vservices',
+ 'parent_id': 'node-250.cisco.com-vservices-routers'}
+
+HOST_DOC = {
+ "config": {
+ "gateway_external_network_id": "",
+ "router_id": "",
+ "handle_internal_only_routers": True,
+ "agent_mode": "legacy",
+ "ex_gw_ports": 4,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "interfaces": 1,
+ "log_agent_heartbeats": False,
+ "use_namespaces": True,
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "routers": 4
+ },
+ "environment": ENV_CONFIG,
+ "host": "node-250.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-250.cisco.com",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones" +
+ "/internal/node-250.cisco.com",
+ "last_scanned": datetime.datetime.utcnow(),
+ "name": "node-250.cisco.com",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-250.cisco.com",
+ "object_name": "node-250.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:47.000000"
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:48.000000"
+ },
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:41.000000"
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:52.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+}
+
+NETWORK_DOC = {
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.0.0/24"
+ ],
+ "environment": ENV_CONFIG,
+ "id": "c64adb76-ad9d-4605-9f5e-123456781234",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/8c1751e0ce714736a63fee3c776164da/8c1751e0ce71" +
+ "4736a63fee3c776164da-networks/c64adb76-ad9d-4605-9f5e-123456781234",
+ "last_scanned": datetime.datetime.utcnow(),
+ "mtu": 1500,
+ "name": "admin_floating_net",
+ "name_path": "/" + ENV_CONFIG + "/Projects/admin/Networks/admin_floating_net",
+ "network": "c64adb76-ad9d-4605-9f5e-123456781234",
+ "object_name": "admin_floating_net",
+ "parent_id": "8c1751e0ce714736a63fee3c776164da-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "admin",
+ "provider:network_type": "flat",
+ "provider:physical_network": "physnet1",
+ "provider:segmentation_id": None,
+ "router:external": True,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnets": {
+ "admin_floating_net__subnet": {
+ "allocation_pools": [
+ {
+ "end": "172.16.0.254",
+ "start": "172.16.0.130"
+ }
+ ],
+ "id": "a5336853-cbc0-49e8-8401-a093e8bab7bb",
+ "network_id": "c64adb76-ad9d-4605-9f5e-123456781234",
+ "ipv6_ra_mode": None,
+ "ipv6_address_mode": None,
+ "ip_version": 4,
+ "tenant_id": "8c1751e0ce714736a63fee3c776164da",
+ "cidr": "172.16.0.0/24",
+ "dns_nameservers": [
+
+ ],
+ "name": "admin_floating_net__subnet",
+ "subnetpool_id": None,
+ "gateway_ip": "172.16.0.1",
+ "host_routes": [
+
+ ],
+ "enable_dhcp": False,
+ }
+ },
+ "subnets_id": [
+ "a5336853-cbc0-49e8-8401-a093e8bab7bb"
+ ],
+ "tenant_id": "8c1751e0ce714736a63fee3c776164da",
+ "type": "network"
+}
diff --git a/app/test/event_based_scan/test_data/event_payload_router_delete.py b/app/test/event_based_scan/test_data/event_payload_router_delete.py
new file mode 100644
index 0000000..8ab8cc3
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_router_delete.py
@@ -0,0 +1,59 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_ROUTER_DELETE = {
+ '_context_request_id': 'req-8b2dd9ba-5faa-4471-94c3-fb41781eef8d', '_unique_id': 'c7417f771ee74bb19036b06e685c93dc',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_auth_token': 'gAAAAABYE7T7789XjB_Nir9PykWTIpDNI0VhgtVQJNyGVImHnug2AVRX9e2JDcXe8F73eNmFepASsoCfqvZet9qN' +
+ '38vrX6GqzL89Quf6pQyLxgRorMv6RlScSCDBQzE8Hj5szSYi_a7F_O2Lr77omUiLi2R_Ludt25mcMiuaMgPknJ2b' +
+ 'joAyV_-eE_8CrSbdJ5Dk1MaCSq5K',
+ '_context_user_name': 'admin',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_timestamp': '2016-10-28 20:31:27.902723', 'message_id': '569118ad-1f5b-4a50-96ec-f160ebbb1b34',
+ 'payload': {'router_id': 'bde87a5a-7968-4f3b-952c-e87681a96078'}, '_context_resource_uuid': None,
+ 'event_type': 'router.delete.end', '_context_project_name': 'calipso-project', 'priority': 'INFO',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_roles': ['_member_', 'admin'],
+ '_context_project_domain': None, '_context_user_domain': None, '_context_read_only': False,
+ '_context_is_admin': True, '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_domain': None,
+ '_context_show_deleted': False, '_context_tenant_name': 'calipso-project', 'publisher_id': 'network.node-6.cisco.com',
+ 'timestamp': '2016-10-28 20:31:37.012032'}
+
+ROUTER_DOCUMENT = {
+ "admin_state_up": True,
+ "enable_snat": 1,
+ "environment": ENV_CONFIG,
+ "gw_port_id": None,
+ "host": "node-6.cisco.com",
+ "id": "node-6.cisco.com-qrouter-bde87a5a-7968-4f3b-952c-e87681a96078",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-6.cisco.com/node-6.cisco.com-vservices/node-6.cisco.com-vservices-routers/qrouter-bde87a5a" +
+ "-7968-4f3b-952c-e87681a96078",
+ "last_scanned": 0,
+ "local_service_id": "node-6.cisco.com-qrouter-bde87a5a-7968-4f3b-952c-e87681a96078",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "1234",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com/" +
+ "Vservices/Gateways/router-1234",
+ "network": [
+ "c64adb76-ad9d-4605-9f5e-bd6dbe325cfb"
+ ],
+ "object_name": "router-1234",
+ "parent_id": "node-6.cisco.com-vservices-routers",
+ "parent_text": "Gateways",
+ "parent_type": "vservice_routers_folder",
+ "service_type": "router",
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "vservice"
+}
diff --git a/app/test/event_based_scan/test_data/event_payload_router_update.py b/app/test/event_based_scan/test_data/event_payload_router_update.py
new file mode 100644
index 0000000..b0a917e
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_router_update.py
@@ -0,0 +1,271 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_ROUTER_UPDATE = {
+ '_context_request_id': 'req-da45908c-0765-4f8a-9fac-79246901de41', '_unique_id': '80723cc09a4748c6b13214dcb867719e',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_user': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_auth_token': 'gAAAAABYE7T7789XjB_Nir9PykWTIpDNI0VhgtVQJNyGVImHnug2AVRX9e2JDcXe8F73eNmFepASsoCfqvZet9q' +
+ 'N38vrX6GqzL89Quf6pQyLxgRorMv6RlScSCDBQzE8Hj5szSYi_a7F_O2Lr77omUiLi2R_Ludt25mcMiuaMgPkn' +
+ 'J2bjoAyV_-eE_8CrSbdJ5Dk1MaCSq5K',
+ '_context_user_name': 'admin',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_timestamp': '2016-10-28 20:29:35.548123', 'message_id': '42c0ca64-cea1-4c89-a059-72abf7990c40',
+ 'payload': {
+ 'router': {'id': 'bde87a5a-7968-4f3b-952c-e87681a96078', 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'ha': False, 'distributed': False, 'name': 'abc', 'status': 'ACTIVE', 'external_gateway_info': None,
+ 'admin_state_up': True, 'routes': []}}, '_context_resource_uuid': None,
+ 'event_type': 'router.update.end', '_context_project_name': 'calipso-project', 'priority': 'INFO',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_roles': ['_member_', 'admin'],
+ '_context_project_domain': None, '_context_user_domain': None, '_context_read_only': False,
+ '_context_is_admin': True, '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_domain': None,
+ '_context_show_deleted': False, '_context_tenant_name': 'calipso-project', 'publisher_id': 'network.node-250.cisco.com',
+ 'timestamp': '2016-10-28 20:29:39.986161'}
+
+ROUTER_VSERVICE = {'host': 'node-250.cisco.com', 'service_type': 'router', 'name': '1234',
+ 'id': 'node-250.cisco.com-qrouter-bde87a5a-7968-4f3b-952c-e87681a96078',
+ 'local_service_id': 'node-250.cisco.com-qrouter-bde87a5a-7968-4f3b-952c-e87681a96078',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'status': 'ACTIVE',
+ 'master_parent_type': 'vservices_folder',
+ 'admin_state_up': 1, 'parent_type': 'vservice_routers_folder', 'enable_snat': 1,
+ 'parent_text': 'Gateways',
+ 'gw_port_id': 'e2f31c24-d0f9-499e-a8b1-883941543aa4',
+ 'master_parent_id': 'node-250.cisco.com-vservices',
+ 'parent_id': 'node-250.cisco.com-vservices-routers'}
+
+ROUTER_DOCUMENT = {
+ "admin_state_up": True,
+ "enable_snat": 1,
+ "environment": ENV_CONFIG,
+ "gw_port_id": "e2f31c24-d0f9-499e-a8b1-883941543aa4",
+ "host": "node-250.cisco.com",
+ "id": "node-250.cisco.com-qrouter-bde87a5a-7968-4f3b-952c-e87681a96078",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones/internal" +
+ "/node-250.cisco.com/node-250.cisco.com-vservices/node-250.cisco.com-vservices-routers/qrouter-bde87a5a" +
+ "-7968-4f3b-952c-e87681a96078",
+ "last_scanned": 0,
+ "local_service_id": "node-250.cisco.com-qrouter-bde87a5a-7968-4f3b-952c-e87681a96078",
+ "master_parent_id": "node-250.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "1234",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-250.cisco.com/" +
+ "Vservices/Gateways/router-1234",
+ "network": [
+ "a55ff1e8-3821-4e5f-bcfd-07df93720a4f"
+ ],
+ "object_name": "router-1234",
+ "parent_id": "node-250.cisco.com-vservices-routers",
+ "parent_text": "Gateways",
+ "parent_type": "vservice_routers_folder",
+ "service_type": "router",
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "vservice"
+}
+
+EVENT_PAYLOAD_ROUTER_SET_GATEWAY = {
+ 'publisher_id': 'network.node-250.cisco.com',
+ '_context_request_id': 'req-79d53b65-47b8-46b2-9a72-3f4031e2d605',
+ '_context_project_name': 'calipso-project', '_context_show_deleted': False,
+ '_context_user_name': 'admin', '_context_timestamp': '2016-11-02 21:44:31.156447',
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', 'payload': {
+ 'router': {'id': 'bde87a5a-7968-4f3b-952c-e87681a96078', 'admin_state_up': True, 'routes': [],
+ 'status': 'ACTIVE', 'ha': False, 'name': 'test_namespace', 'distributed': False,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'external_gateway_info': {'external_fixed_ips': [
+ {'ip_address': '172.16.0.144', 'subnet_id': 'a5336853-cbc0-49e8-8401-a093e8bab7bb'}],
+ 'network_id': 'a55ff1e8-3821-4e5f-bcfd-07df93720a4f',
+ 'enable_snat': True}}},
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_read_only': False,
+ '_context_auth_token': 'gAAAAABYGlU6mEqntx5E9Nss203DIKH352JKSZP0RsJrAJQ_PfjyZEAzYcFvMh4FYVRDRWLvu0cSDsvUk1ILu' +
+ 'nHkpNF28pwcvkBgVModV2Xd2_BW2QbBa2csCOXYiN0LE2uOo3BkrLDEcblvJVT0XTJdDhrBldfyCH0_xSfJ7_' +
+ 'wzdy8bB34HwHq2w0S3Okp8Tk_Zx_-xpIqB',
+ 'priority': 'INFO', 'timestamp': '2016-11-02 21:44:35.627776',
+ '_context_roles': ['_member_', 'admin'], '_context_resource_uuid': None,
+ '_context_user_domain': None, '_context_project_domain': None,
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ 'message_id': '71889925-14ce-40c3-a3dc-f26731b10b26',
+ 'event_type': 'router.update.end',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_unique_id': '9e6ab72c5901451f81748e0aa654ae25',
+ '_context_tenant_name': 'calipso-project', '_context_is_admin': True,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_domain': None}
+
+EVENT_PAYLOAD_ROUTER_DEL_GATEWAY = {
+ '_context_show_deleted': False, '_context_timestamp': '2016-11-03 18:48:40.420170', '_context_read_only': False,
+ 'publisher_id': 'network.node-250.cisco.com',
+ '_context_auth_token': 'gAAAAABYG4UUGbe9bykUJUPY0lKye578aF0RrMCc7nA21eLbhpwcsh5pWWqz6hnOi7suUCUtr1DPTbqF1M8CVJ' +
+ '9FT2EevbqiahcyphrV2VbmP5_tebOcIHIPJ_f_K3KYJM1C6zgcWgdf9KFu_8t_G99wd1MwWBrZyUUElXgSNv48' +
+ 'W4uaCKcbYclnZW78lgXVik5x6WLT_j5V',
+ '_context_user_name': 'admin',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_unique_id': '266f2bb0ab2c4a328ae0759d01b0035b',
+ 'timestamp': '2016-11-03 18:48:41.634214', '_context_roles': ['_member_', 'admin'],
+ 'event_type': 'router.update.end',
+ '_context_user_domain': None, '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_is_admin': True,
+ '_context_tenant_name': 'calipso-project', '_context_project_domain': None, '_context_domain': None,
+ 'priority': 'INFO',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'message_id': '5272cd90-7151-4d13-8c1f-e8ff2db773a1',
+ '_context_project_name': 'calipso-project', '_context_resource_uuid': None, 'payload': {
+ 'router': {'id': 'bde87a5a-7968-4f3b-952c-e87681a96078', 'external_gateway_info': None, 'distributed': False,
+ 'name': 'TEST_AAA', 'routes': [], 'ha': False, 'admin_state_up': True,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'status': 'ACTIVE'}},
+ '_context_request_id': 'req-d7e73189-4709-4234-8b4c-fb6b4dc2017b'}
+
+PORTS = {
+ "admin_state_up": True,
+ "allowed_address_pairs": [
+
+ ],
+ "binding:host_id": "node-250.cisco.com",
+ "binding:profile": {
+
+ },
+ "binding:vif_details": {
+ "port_filter": True,
+ "ovs_hybrid_plug": True
+ },
+ "binding:vif_type": "ovs",
+ "binding:vnic_type": "normal",
+ "device_id": "9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "device_owner": "network:router_interface",
+ "dns_assignment": [
+ {
+ "hostname": "host-172-16-1-1",
+ "fqdn": "host-172-16-1-1.openstacklocal.",
+ "ip_address": "172.16.1.1"
+ }
+ ],
+ "dns_name": "",
+ "environment": ENV_CONFIG,
+ "extra_dhcp_opts": [
+
+ ],
+ "fixed_ips": [
+ {
+ "subnet_id": "c1287696-224b-4a72-9f1d-d45176671bce",
+ "ip_address": "172.16.1.1"
+ }
+ ],
+ "id": "e2f31c24-d0f9-499e-a8b1-883941543aa4",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b" +
+ "0ae4973c8375ddf40-networks/a55ff1e8-3821-4e5f-bcfd-07df93720a4f/a55ff1e8-3821-4e5f-bcfd-07df93720a4" +
+ "f-ports/e2f31c24-d0f9-499e-a8b1-883941543aa4",
+ "last_scanned": 0,
+ "mac_address": "fa:16:3e:ee:9a:46",
+ "name": "fa:16:3e:ee:9a:46",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/calipso-net2/Ports/fa:16:3e:ee:9a:46",
+ "network_id": "a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "object_name": "fa:16:3e:ee:9a:46",
+ "parent_id": "a55ff1e8-3821-4e5f-bcfd-07df93720a4f-ports",
+ "parent_text": "Ports",
+ "parent_type": "ports_folder",
+ "port_security_enabled": False,
+ "project": "calipso-project",
+ "security_groups": [
+
+ ],
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "port"
+}
+
+NETWORK_DOC = {
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.4.0/24"
+ ],
+ "environment": ENV_CONFIG,
+ "id": "a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b" +
+ "0ae4973c8375ddf40-networks/a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "last_scanned": 0,
+ "mtu": 1400,
+ "name": "calipso-net2",
+ "name_path": "/" + ENV_CONFIG + "/Projects/calipso-project/Networks/calipso-net2",
+ "network": "a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "object_name": "calipso-net2",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "calipso-project",
+ "provider:network_type": "vxlan",
+ "provider:physical_network": None,
+ "provider:segmentation_id": 0,
+ "router:external": False,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnets": {},
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "network"
+}
+
+HOST_DOC = {
+ "config": {
+ "gateway_external_network_id": "",
+ "router_id": "",
+ "handle_internal_only_routers": True,
+ "agent_mode": "legacy",
+ "ex_gw_ports": 4,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "interfaces": 1,
+ "log_agent_heartbeats": False,
+ "use_namespaces": True,
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "routers": 4
+ },
+ "environment": ENV_CONFIG,
+ "host": "node-250.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-250.cisco.com",
+ "id_path": "/" + ENV_CONFIG + "/" + ENV_CONFIG + "-regions/RegionOne/RegionOne-availability_zones" +
+ "/internal/node-250.cisco.com",
+ "last_scanned": 0,
+ "name": "node-250.cisco.com",
+ "name_path": "/" + ENV_CONFIG + "/Regions/RegionOne/Availability Zones/internal/node-250.cisco.com",
+ "object_name": "node-250.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:47.000000"
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:48.000000"
+ },
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:41.000000"
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-11-02T21:19:52.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+} \ No newline at end of file
diff --git a/app/test/event_based_scan/test_data/event_payload_subnet_add.py b/app/test/event_based_scan/test_data/event_payload_subnet_add.py
new file mode 100644
index 0000000..7167f4c
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_subnet_add.py
@@ -0,0 +1,124 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import datetime
+
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+NETWORK_DOC = {'port_security_enabled': True, 'status': 'ACTIVE', 'subnet_ids': [], 'parent_type': 'networks_folder',
+ 'parent_id': '75c0eb79ff4a42b0ae4973c8375ddf40-networks', 'parent_text': 'Networks', 'subnets': {},
+ 'admin_state_up': True, 'show_in_tree': True, 'project': 'calipso-project',
+ 'name_path': '/' + ENV_CONFIG + '/Projects/calipso-project/Networks/testsubnetadd',
+ 'router:external': False,
+ 'provider:physical_network': None,
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0' +
+ 'ae4973c8375ddf40-networks/1bb0ba6c-6863-4121-ac89-93f81a9da2b0',
+ 'object_name': 'testsubnetadd', 'provider:segmentation_id': 46, 'provider:network_type': 'vxlan',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'environment': ENV_CONFIG, 'name': 'testsubnetadd',
+ 'last_scanned': '2016-10-13 00:20:59.280329', 'id': '1bb0ba6c-6863-4121-ac89-93f81a9da2b0', 'cidrs': [],
+ 'type': 'network', 'network': '1bb0ba6c-6863-4121-ac89-93f81a9da2b0', 'shared': False, 'mtu': 1400}
+
+EVENT_PAYLOAD_SUBNET_ADD = {
+ 'payload': {
+ 'subnet': {'dns_nameservers': [], 'ipv6_address_mode': None, 'ipv6_ra_mode': None, 'gateway_ip': '172.16.10.1',
+ 'allocation_pools': [{'start': '172.16.10.2', 'end': '172.16.10.126'}], 'enable_dhcp': True,
+ 'id': 'e950055d-231c-4380-983c-a258ea958d58', 'network_id': '1bb0ba6c-6863-4121-ac89-93f81a9da2b0',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'ip_version': 4, 'cidr': '172.16.10.0/25',
+ 'subnetpool_id': None, 'name': 'testsubnetadd', 'host_routes': []}}, '_context_domain': None,
+ 'timestamp': '2016-10-13 00:20:59.776358', '_context_project_domain': None, '_context_user_domain': None,
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'publisher_id': 'network.node-6.cisco.com',
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ 'event_type': 'subnet.create.end', 'message_id': '90581321-e9c9-4112-8fe6-38ebf57d5b6b',
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_tenant_name': 'calipso-project',
+ '_context_project_name': 'calipso-project', '_context_user_name': 'admin', '_context_resource_uuid': None,
+ '_unique_id': 'e8b328229a724938a6bc63f9db737f49', '_context_request_id': 'req-20cfc138-4e1a-472d-b996-7f27ac58446d',
+ 'priority': 'INFO', '_context_roles': ['_member_', 'admin'],
+ '_context_auth_token': 'gAAAAABX_tLMEzC9KhdcD20novcuvgwmpQkwV9hOk86d4AZlsQwXSRbCwBZgUPQZco4VsuCg59_gFeM_scBVmI' +
+ 'dDysNUrAhZctDzXneM0cb5nBtjJTfJPpI2_kKgAuGDBARrHZpNs-vPg-SjMtu87w2rgTKfda6idTMKWG3ipe' +
+ '-jXrgNN7p-2kkJzGhZXbMaaeBs3XU-X_ew',
+ '_context_read_only': False,
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_is_admin': True, '_context_show_deleted': False,
+ '_context_timestamp': '2016-10-13 00:20:59.307917'}
+
+EVENT_PAYLOAD_REGION = {
+ 'RegionOne': {
+ 'object_name': 'RegionOne', 'id': 'RegionOne', 'name': 'RegionOne',
+ 'environment': ENV_CONFIG,
+ 'last_scanned': datetime.datetime.utcnow(),
+ 'name_path': '/' + ENV_CONFIG + '/Regions/RegionOne',
+ 'parent_id': ENV_CONFIG + '-regions', 'parent_type': 'regions_folder',
+ 'endpoints': {'nova': {'id': '274cbbd9fd6d4311b78e78dd3a1df51f',
+ 'adminURL': 'http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'compute',
+ 'publicURL': 'http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da'},
+ 'heat-cfn': {'id': '0f04ec6ed49f4940822161bf677bdfb2',
+ 'adminURL': 'http://192.168.0.2:8000/v1',
+ 'service_type': 'cloudformation',
+ 'publicURL': 'http://172.16.0.3:8000/v1',
+ 'internalURL': 'http://192.168.0.2:8000/v1'},
+ 'nova_ec2': {'id': '390dddc753cc4d378b489129d06c4b7d',
+ 'adminURL': 'http://192.168.0.2:8773/services/Admin',
+ 'service_type': 'ec2',
+ 'publicURL': 'http://172.16.0.3:8773/services/Cloud',
+ 'internalURL': 'http://192.168.0.2:8773/services/Cloud'},
+ 'glance': {'id': '475c6c77a94e4e63a5a0f0e767f697a8',
+ 'adminURL': 'http://192.168.0.2:9292',
+ 'service_type': 'image',
+ 'publicURL': 'http://172.16.0.3:9292',
+ 'internalURL': 'http://192.168.0.2:9292'},
+ 'swift': {'id': '12e78e06595f48339baebdb5d4309c70',
+ 'adminURL': 'http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'object-store',
+ 'publicURL': 'http://172.16.0.3:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da'},
+ 'swift_s3': {'id': '4f655c8f2bef46a0a7ba4a20bba53666',
+ 'adminURL': 'http://192.168.0.2:8080',
+ 'service_type': 's3',
+ 'publicURL': 'http://172.16.0.3:8080',
+ 'internalURL': 'http://192.168.0.2:8080'},
+ 'keystone': {'id': '404cceb349614eb39857742970408301',
+ 'adminURL': 'http://192.168.0.2:35357/v2.0',
+ 'service_type': 'identity',
+ 'publicURL': 'http://172.16.0.3:5000/v2.0',
+ 'internalURL': 'http://192.168.0.2:5000/v2.0'},
+ 'cinderv2': {'id': '2c30937688e944889db4a64fab6816e6',
+ 'adminURL': 'http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'volumev2',
+ 'publicURL': 'http://172.16.0.3:8776/v2/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da'},
+ 'novav3': {'id': '1df917160dfb4ce5b469764fde22b3ab',
+ 'adminURL': 'http://192.168.0.2:8774/v3',
+ 'service_type': 'computev3',
+ 'publicURL': 'http://172.16.0.3:8774/v3',
+ 'internalURL': 'http://192.168.0.2:8774/v3'},
+ 'ceilometer': {'id': '617177a3dcb64560a5a79ab0a91a7225',
+ 'adminURL': 'http://192.168.0.2:8777',
+ 'service_type': 'metering',
+ 'publicURL': 'http://172.16.0.3:8777',
+ 'internalURL': 'http://192.168.0.2:8777'},
+ 'neutron': {'id': '8dc28584da224c4b9671171ead3c982a',
+ 'adminURL': 'http://192.168.0.2:9696',
+ 'service_type': 'network',
+ 'publicURL': 'http://172.16.0.3:9696',
+ 'internalURL': 'http://192.168.0.2:9696'},
+ 'cinder': {'id': '05643f2cf9094265b432376571851841',
+ 'adminURL': 'http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'volume',
+ 'publicURL': 'http://172.16.0.3:8776/v1/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da'},
+ 'heat': {'id': '9e60268a5aaf422d9e42f0caab0a19b4',
+ 'adminURL': 'http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da',
+ 'service_type': 'orchestration',
+ 'publicURL': 'http://172.16.0.3:8004/v1/8c1751e0ce714736a63fee3c776164da',
+ 'internalURL': 'http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da'}},
+ 'show_in_tree': True,
+ 'id_path': '/' + ENV_CONFIG + '/' + ENV_CONFIG + '-regions/RegionOne',
+ 'type': 'region'}}
diff --git a/app/test/event_based_scan/test_data/event_payload_subnet_delete.py b/app/test/event_based_scan/test_data/event_payload_subnet_delete.py
new file mode 100644
index 0000000..55a785d
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_subnet_delete.py
@@ -0,0 +1,95 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+EVENT_PAYLOAD_SUBNET_DELETE = {
+ 'payload': {'subnet_id': '88442b4a-e62d-4d72-9d18-b8d6973eb3da'},
+ '_context_auth_token': 'gAAAAABYGRxBKUKuNjrN4Z9H5HNhfpfS9h671aqjRNwPT_2snUk5OI52zTpAh-9yjIlcJOZRXHUlWZW7R'+
+ '-vNAjUwdSJ4ILwMW9smDT8hLTsBIki-QtJl1nSSlfhVAqhMsnrQxREJeagESGuvsR3BxHgMVrCt1Vh5wR9'+
+ 'E1_pHgn0WFpwVJEN0U8IxNfBvU8uLuIHq1j6XRiiY',
+ '_context_user_domain': None, '_context_user_name': 'admin', '_context_read_only': False,
+ 'publisher_id': 'network.node-6.cisco.com', 'event_type': 'subnet.delete.end',
+ 'timestamp': '2016-11-01 22:58:04.504790', 'priority': 'INFO',
+ '_context_roles': ['_member_', 'admin'],
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ '_unique_id': 'f79384f4c7764bdc93ee2469d79123d1',
+ '_context_tenant_name': 'calipso-project',
+ '_context_request_id': 'req-cbb08126-3027-49f0-a896-aedf05cc3389',
+ '_context_domain': None, '_context_is_admin': True,
+ '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_project_domain': None,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9',
+ '_context_project_name': 'calipso-project',
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_resource_uuid': None,
+ '_context_timestamp': '2016-11-01 22:58:02.675098', '_context_show_deleted': False,
+ 'message_id': '7bd8402e-8f1f-4f8c-afc2-5042b3388ae7',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40'}
+
+
+EVENT_PAYLOAD_NETWORK = {
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.10.0/25"
+ ],
+ "environment": ENV_CONFIG,
+ "id": "121c727b-6376-4a86-a5a8-793dfe7a8ef4",
+ "id_path": "/"+ENV_CONFIG+"/"+ENV_CONFIG+"-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a" +
+ "42b0ae4973c8375ddf40-networks/121c727b-6376-4a86-a5a8-793dfe7a8ef4",
+ "last_scanned": 0,
+ "mtu": 1400,
+ "name": "asad",
+ "name_path": "/"+ENV_CONFIG+"/Projects/calipso-project/Networks/asad",
+ "network": "121c727b-6376-4a86-a5a8-793dfe7a8ef4",
+ "object_name": "asad",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "calipso-project",
+ "provider:network_type": "vxlan",
+ "provider:physical_network": None,
+ "provider:segmentation_id": 18,
+ "router:external": False,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnets": {
+ "testsubnet": {
+ "subnetpool_id": None,
+ "enable_dhcp": True,
+ "ipv6_ra_mode": None,
+ "dns_nameservers": [
+
+ ],
+ "name": "testsubnet",
+ "ipv6_address_mode": None,
+ "ip_version": 4,
+ "gateway_ip": "172.16.10.1",
+ "network_id": "121c727b-6376-4a86-a5a8-793dfe7a8ef4",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "allocation_pools": [
+ {
+ "start": "172.16.10.2",
+ "end": "172.16.10.126"
+ }
+ ],
+ "id": "88442b4a-e62d-4d72-9d18-b8d6973eb3da",
+ "host_routes": [
+
+ ],
+ "cidr": "172.16.10.0/25"
+ }
+ },
+ "subnet_ids": [
+ "88442b4a-e62d-4d72-9d18-b8d6973eb3da"
+ ],
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "network"
+}
diff --git a/app/test/event_based_scan/test_data/event_payload_subnet_update.py b/app/test/event_based_scan/test_data/event_payload_subnet_update.py
new file mode 100644
index 0000000..5f547c5
--- /dev/null
+++ b/app/test/event_based_scan/test_data/event_payload_subnet_update.py
@@ -0,0 +1,76 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from test.event_based_scan.config.test_config import ENV_CONFIG
+
+NETWORK_DOC = {
+ 'port_security_enabled': True, 'status': 'ACTIVE',
+ 'subnets_id': ['393a1f80-4277-4c9a-b44c-0bc05a5121c6'], 'parent_type': 'networks_folder',
+ 'parent_id': '75c0eb79ff4a42b0ae4973c8375ddf40-networks', 'parent_text': 'Networks',
+ 'subnets': {'test': {'name': 'test', 'subnetpool_id': None, 'id': '393a1f80-4277-4c9a-b44c-0bc05a5121c6',
+ 'network_id': '0abe6331-0d74-4bbd-ad89-a5719c3793e4', 'gateway_ip': '172.16.12.1',
+ 'ipv6_address_mode': None, 'dns_nameservers': [], 'ipv6_ra_mode': None, 'cidr': '172.16.12.0/24',
+ 'allocation_pools': [{'start': '172.16.12.2', 'end': '172.16.12.254'}], 'enable_dhcp': True,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'host_routes': [], 'ip_version': 4},
+ },
+ 'admin_state_up': True, 'show_in_tree': True, 'project': 'calipso-project',
+ 'name_path': '/'+ENV_CONFIG+'/Projects/calipso-project/Networks/testsubnetadd', 'router:external': False,
+ 'provider:physical_network': None,
+ 'id_path': '/'+ENV_CONFIG+'/'+ENV_CONFIG+'-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0'+
+ 'ae4973c8375ddf40-networks/0abe6331-0d74-4bbd-ad89-a5719c3793e4',
+ 'object_name': 'testsubnetadd', 'provider:segmentation_id': 46, 'provider:network_type': 'vxlan',
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'environment': ENV_CONFIG, 'name': 'testsubnetadd',
+ 'last_scanned': '2016-10-13 00:20:59.280329', 'id': '0abe6331-0d74-4bbd-ad89-a5719c3793e4',
+ 'cidrs': ['172.16.12.0/24'],
+ 'type': 'network', 'network': '0abe6331-0d74-4bbd-ad89-a5719c3793e4', 'shared': False, 'mtu': 1400}
+
+
+EVENT_PAYLOAD_SUBNET_UPDATE = {
+ 'publisher_id': 'network.node-6.cisco.com', '_context_show_deleted': False, '_context_project_domain': None,
+ '_context_resource_uuid': None, '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'message_id': '548650b4-2cba-45b6-9b3b-b87cb5c3246e',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_unique_id': '9ffd93fe355141d9976c6808a9ce9b7d',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_read_only': False,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_timestamp': '2016-10-25 00:00:18.505443',
+ 'priority': 'INFO', '_context_roles': ['_member_', 'admin'], '_context_project_name': 'calipso-project',
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_user_name': 'admin',
+ 'timestamp': '2016-10-25 00:00:19.354342', '_context_request_id': 'req-62945d8f-a233-44c8-aa53-f608ad92fd56',
+ '_context_tenant_name': 'calipso-project', '_context_domain': None, 'payload': {
+ 'subnet': {'name': 'port', 'subnetpool_id': None, 'id': '393a1f80-4277-4c9a-b44c-0bc05a5121c6',
+ 'network_id': '0abe6331-0d74-4bbd-ad89-a5719c3793e4', 'gateway_ip': '172.16.12.1',
+ 'ipv6_address_mode': None, 'dns_nameservers': [], 'ipv6_ra_mode': None, 'cidr': '172.16.12.0/24',
+ 'allocation_pools': [{'start': '172.16.12.2', 'end': '172.16.12.254'}], 'enable_dhcp': True,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'host_routes': [], 'ip_version': 4}},
+ '_context_is_admin': True, '_context_user_domain': None, 'event_type': 'subnet.update.end',
+ '_context_auth_token': 'gAAAAABYDp0ZacwkUNIRvtiS-3qjLQFZKbkOtTmvuoKX9yM8yCIvl-eZmMC_SPjwPAMJcd8qckE77lLpQ' +
+ 'Sx0lWB67mT5jQA-tmp8bcz26kXXr8KlGCicxxjkYTYkJQhC9w8BbGc36CpbRBzIKlOrPtPXUYZrUmPgInQ' +
+ 'qCNA-eDeMyJ-AiA1zmNSZK3R43YIJtnDYieLQvX2P'}
+
+EVENT_PAYLOAD_SUBNET_UPDATE_1 = {
+ 'publisher_id': 'network.node-6.cisco.com', '_context_show_deleted': False, '_context_project_domain': None,
+ '_context_resource_uuid': None, '_context_tenant': '75c0eb79ff4a42b0ae4973c8375ddf40',
+ 'message_id': 'd0f7545f-a2d6-4b0e-a658-01e4de4ecd19',
+ '_context_user_identity': '13baa553aae44adca6615e711fd2f6d9 75c0eb79ff4a42b0ae4973c8375ddf40 - - -',
+ '_context_tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_unique_id': '1ca167b1317d4523a31b2ae99b25d67c',
+ '_context_project_id': '75c0eb79ff4a42b0ae4973c8375ddf40', '_context_read_only': False,
+ '_context_user_id': '13baa553aae44adca6615e711fd2f6d9', '_context_timestamp': '2016-10-25 00:03:21.079403',
+ 'priority': 'INFO', '_context_roles': ['_member_', 'admin'], '_context_project_name': 'calipso-project',
+ '_context_user': '13baa553aae44adca6615e711fd2f6d9', '_context_user_name': 'admin',
+ 'timestamp': '2016-10-25 00:03:22.689115', '_context_request_id': 'req-7a19e8d7-51f6-470e-9035-5e007c9b1f89',
+ '_context_tenant_name': 'calipso-project', '_context_domain': None, 'payload': {
+ 'subnet': {'name': 'port', 'subnetpool_id': None, 'id': '393a1f80-4277-4c9a-b44c-0bc05a5121c6',
+ 'network_id': '0abe6331-0d74-4bbd-ad89-a5719c3793e4', 'gateway_ip': None, 'ipv6_address_mode': None,
+ 'dns_nameservers': [], 'ipv6_ra_mode': None, 'cidr': '172.16.12.0/24',
+ 'allocation_pools': [{'start': '172.16.12.2', 'end': '172.16.12.254'}], 'enable_dhcp': True,
+ 'tenant_id': '75c0eb79ff4a42b0ae4973c8375ddf40', 'host_routes': [], 'ip_version': 4}},
+ '_context_is_admin': True, '_context_user_domain': None, 'event_type': 'subnet.update.end',
+ '_context_auth_token': 'gAAAAABYDp0ZacwkUNIRvtiS-3qjLQFZKbkOtTmvuoKX9yM8yCIvl-eZmMC_SPjwPAMJcd8qckE77lLpQSx0l'+
+ 'WB67mT5jQA-tmp8bcz26kXXr8KlGCicxxjkYTYkJQhC9w8BbGc36CpbRBzIKlOrPtPXUYZrUmPgInQqCNA-eD'+
+ 'eMyJ-AiA1zmNSZK3R43YIJtnDYieLQvX2P'}
diff --git a/app/test/event_based_scan/test_event.py b/app/test/event_based_scan/test_event.py
new file mode 100644
index 0000000..e3e8ab9
--- /dev/null
+++ b/app/test/event_based_scan/test_event.py
@@ -0,0 +1,55 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import re
+import unittest
+
+from discover.configuration import Configuration
+from test.event_based_scan.config.test_config \
+ import MONGODB_CONFIG, ENV_CONFIG, COLLECTION_CONFIG
+from utils.inventory_mgr import InventoryMgr
+from utils.logging.console_logger import ConsoleLogger
+from utils.mongo_access import MongoAccess
+
+
+class TestEvent(unittest.TestCase):
+ def setUp(self):
+ self.log = ConsoleLogger()
+ self.mongo_config = MONGODB_CONFIG
+ self.env = ENV_CONFIG
+ self.collection = COLLECTION_CONFIG
+
+ MongoAccess.set_config_file(self.mongo_config)
+ self.conf = Configuration()
+ self.conf.use_env(self.env)
+
+ self.inv = InventoryMgr()
+ self.inv.set_collections(self.collection)
+ self.item_ids = []
+
+ def set_item(self, document):
+ self.inv.set(document)
+ self.item_ids.append(document['id'])
+
+ def assert_empty_by_id(self, object_id):
+ doc = self.inv.get_by_id(self.env, object_id)
+ self.assertIsNone(doc)
+
+ def tearDown(self):
+ for item_id in self.item_ids:
+ item = self.inv.get_by_id(self.env, item_id)
+ # delete children
+ if item:
+ regexp = re.compile('^{}/'.format(item['id_path']))
+ self.inv.delete('inventory', {'id_path': {'$regex': regexp}})
+
+ # delete target item
+ self.inv.delete('inventory', {'id': item_id})
+ item = self.inv.get_by_id(self.env, item_id)
+ self.assertIsNone(item)
diff --git a/app/test/event_based_scan/test_event_delete_base.py b/app/test/event_based_scan/test_event_delete_base.py
new file mode 100644
index 0000000..1ccabb3
--- /dev/null
+++ b/app/test/event_based_scan/test_event_delete_base.py
@@ -0,0 +1,64 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from bson import ObjectId
+
+from discover.clique_finder import CliqueFinder
+from discover.events.event_base import EventBase
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestEventDeleteBase(TestEvent):
+
+ def setUp(self):
+ super().setUp()
+ self.values = {}
+
+ def set_item_for_deletion(self, object_type, document):
+
+ payload = self.values['payload']
+ self.item_id = payload['{}_id'.format(object_type)]
+ if object_type == 'router':
+ host_id = self.values['publisher_id'].replace("network.", "", 1)
+ self.item_id = "-".join([host_id, "qrouter", self.item_id])
+
+ self.assertEqual(document['id'], self.item_id, msg="Document id and payload id are different")
+
+ item = self.inv.get_by_id(self.env, self.item_id)
+ if not item:
+ self.log.info('{} document is not found, add document for deleting.'.format(object_type))
+
+ # add network document for deleting.
+ self.set_item(document)
+ item = self.inv.get_by_id(self.env, self.item_id)
+ self.assertIsNotNone(item)
+
+ def handle_delete(self, handler: EventBase):
+
+ item = self.inv.get_by_id(self.env, self.item_id)
+ db_id = ObjectId(item['_id'])
+ clique_finder = CliqueFinder()
+
+ # delete item
+ event_result = handler.handle(self.env, self.values)
+ self.assertTrue(event_result.result)
+
+ # check instance delete result.
+ item = self.inv.get_by_id(self.env, self.item_id)
+ self.assertIsNone(item)
+
+ # check links
+ matched_links_source = clique_finder.find_links_by_source(db_id)
+ matched_links_target = clique_finder.find_links_by_target(db_id)
+ self.assertEqual(matched_links_source.count(), 0)
+ self.assertEqual(matched_links_target.count(), 0)
+
+ # check children
+ matched_children = self.inv.get_children(self.env, None, self.item_id)
+ self.assertEqual(len(matched_children), 0)
diff --git a/app/test/event_based_scan/test_instance_add.py b/app/test/event_based_scan/test_instance_add.py
new file mode 100644
index 0000000..24c29b2
--- /dev/null
+++ b/app/test/event_based_scan/test_instance_add.py
@@ -0,0 +1,61 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import patch
+
+from discover.events.event_instance_add import EventInstanceAdd
+from test.event_based_scan.test_data.event_payload_instance_add \
+ import EVENT_PAYLOAD_INSTANCE_ADD, INSTANCES_ROOT, HOST, INSTANCE_DOCUMENT
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestInstanceAdd(TestEvent):
+
+ def insert_instance(self):
+ self.set_item(INSTANCE_DOCUMENT)
+
+ # Patch ScanHost entirely to negate its side effects and supply our own
+ @patch("discover.events.event_instance_add.ScanHost")
+ def test_handle_instance_add(self, scan_host_mock):
+ self.values = EVENT_PAYLOAD_INSTANCE_ADD
+ payload = self.values['payload']
+ self.instance_id = payload['instance_id']
+ host_id = payload['host']
+
+ # prepare instances root, in case it's not there
+ self.set_item(INSTANCES_ROOT)
+
+ # prepare host, in case it's not existed.
+ self.set_item(HOST)
+
+ # check instance document
+ instance = self.inv.get_by_id(self.env, self.instance_id)
+ if instance:
+ self.log.info('instance document exists, delete it first.')
+ self.inv.delete('inventory', {'id': self.instance_id})
+
+ instance = self.inv.get_by_id(self.env, self.instance_id)
+ self.assertIsNone(instance)
+
+ # simulate instance insertion after host scan
+ scan_host_mock.return_value.scan_links.side_effect = self.insert_instance
+
+ # check the return of instance handler.
+ handler = EventInstanceAdd()
+ ret = handler.handle(self.env, self.values)
+
+ self.assertEqual(ret.result, True)
+
+ # check host document
+ host = self.inv.get_by_id(self.env, host_id)
+ self.assertIsNotNone(host)
+
+ # check instance document
+ instance_document = self.inv.get_by_id(self.env, self.instance_id)
+ self.assertIsNotNone(instance_document)
diff --git a/app/test/event_based_scan/test_instance_delete.py b/app/test/event_based_scan/test_instance_delete.py
new file mode 100644
index 0000000..1572e9d
--- /dev/null
+++ b/app/test/event_based_scan/test_instance_delete.py
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_instance_delete import EventInstanceDelete
+from test.event_based_scan.test_data.event_payload_instance_delete import EVENT_PAYLOAD_INSTANCE_DELETE, \
+ INSTANCE_DOCUMENT
+from test.event_based_scan.test_event_delete_base import TestEventDeleteBase
+
+
+class TestInstanceDelete(TestEventDeleteBase):
+
+ def setUp(self):
+ super().setUp()
+ self.values = EVENT_PAYLOAD_INSTANCE_DELETE
+ self.set_item_for_deletion(object_type="instance", document=INSTANCE_DOCUMENT)
+
+ def test_handle_instance_delete(self):
+ self.handle_delete(handler=EventInstanceDelete())
diff --git a/app/test/event_based_scan/test_instance_update.py b/app/test/event_based_scan/test_instance_update.py
new file mode 100644
index 0000000..6abccb5
--- /dev/null
+++ b/app/test/event_based_scan/test_instance_update.py
@@ -0,0 +1,46 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_instance_update import EventInstanceUpdate
+from test.event_based_scan.test_data.event_payload_instance_update import EVENT_PAYLOAD_INSTANCE_UPDATE, INSTANCE_DOCUMENT
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestInstanceUpdate(TestEvent):
+
+ def test_handle_normal_situation(self):
+ self.values = EVENT_PAYLOAD_INSTANCE_UPDATE
+ payload = self.values['payload']
+ self.instance_id = payload['instance_id']
+ self.item_ids.append(self.instance_id)
+ new_name = payload['display_name']
+
+ # preparing instance to be updated
+ instance = self.inv.get_by_id(self.env, self.instance_id)
+ if not instance:
+ self.log.info("instance document is not found, add document for updating")
+
+ # add instance document for updating
+ self.set_item(INSTANCE_DOCUMENT)
+ instance = self.inv.get_by_id(self.env, self.instance_id)
+ self.assertIsNotNone(instance)
+ self.assertEqual(instance['name'], INSTANCE_DOCUMENT['name'])
+
+ name_path = instance['name_path']
+ new_name_path = name_path[:name_path.rindex('/') + 1] + new_name
+
+ # update instance document
+ EventInstanceUpdate().handle(self.env, self.values)
+
+ # get new document
+ instance = self.inv.get_by_id(self.env, self.instance_id)
+
+ # check update result.
+ self.assertEqual(instance['name'], new_name)
+ self.assertEqual(instance['name_path'], new_name_path)
diff --git a/app/test/event_based_scan/test_interface_add.py b/app/test/event_based_scan/test_interface_add.py
new file mode 100644
index 0000000..a9eaac8
--- /dev/null
+++ b/app/test/event_based_scan/test_interface_add.py
@@ -0,0 +1,74 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+
+from discover.events.event_interface_add import EventInterfaceAdd
+from discover.fetchers.api.api_access import ApiAccess
+from discover.fetchers.api.api_fetch_port import ApiFetchPort
+from discover.fetchers.cli.cli_fetch_host_vservice import CliFetchHostVservice
+from discover.fetchers.cli.cli_fetch_vservice_vnics import CliFetchVserviceVnics
+from discover.find_links_for_vservice_vnics import FindLinksForVserviceVnics
+from test.event_based_scan.test_data.event_payload_interface_add import EVENT_PAYLOAD_INTERFACE_ADD, NETWORK_DOC, \
+ EVENT_PAYLOAD_REGION, PORT_DOC, ROUTER_DOCUMENT, HOST, VNIC_DOCS
+from test.event_based_scan.test_event import TestEvent
+from utils.util import encode_router_id
+
+
+class TestInterfaceAdd(TestEvent):
+ def test_handle_interface_add(self):
+ self.values = EVENT_PAYLOAD_INTERFACE_ADD
+ self.payload = self.values['payload']
+ self.interface = self.payload['router_interface']
+
+ self.port_id = self.interface['port_id']
+ self.host_id = self.values["publisher_id"].replace("network.", "", 1)
+ self.router_id = encode_router_id(self.host_id, self.interface['id'])
+
+ self.set_item(NETWORK_DOC)
+ ApiAccess.regions = EVENT_PAYLOAD_REGION
+
+ # mock port data,
+ original_api_get_port = ApiFetchPort.get
+ ApiFetchPort.get = MagicMock(return_value=[PORT_DOC])
+ self.item_ids.append(PORT_DOC['id'])
+
+ # set router document
+ self.set_item(ROUTER_DOCUMENT)
+
+ # set host document
+ self.set_item(HOST)
+
+ # mock add_links
+ original_add_links = FindLinksForVserviceVnics.add_links
+ FindLinksForVserviceVnics.add_links = MagicMock()
+
+ # mock get_vservice
+ original_get_vservice = CliFetchHostVservice.get_vservice
+ CliFetchHostVservice.get_vservice = MagicMock(return_value=ROUTER_DOCUMENT)
+
+ # mock handle_vservice
+ original_handle_service = CliFetchVserviceVnics.handle_service
+ CliFetchVserviceVnics.handle_service = MagicMock(return_value=VNIC_DOCS)
+
+ # handle the notification
+ EventInterfaceAdd().handle(self.env, self.values)
+
+ # reset the method.
+ ApiFetchPort.get = original_api_get_port
+ FindLinksForVserviceVnics.add_links = original_add_links
+ CliFetchHostVservice.get_vservice = original_get_vservice
+ CliFetchVserviceVnics.handle_service = original_handle_service
+
+ # check port and router document
+ port_doc = self.inv.get_by_id(self.env, self.port_id)
+ self.assertIsNotNone(port_doc)
+
+ router_doc = self.inv.get_by_id(self.env, self.router_id)
+ self.assertIn(NETWORK_DOC['id'], router_doc['network'])
diff --git a/app/test/event_based_scan/test_interface_delete.py b/app/test/event_based_scan/test_interface_delete.py
new file mode 100644
index 0000000..b156758
--- /dev/null
+++ b/app/test/event_based_scan/test_interface_delete.py
@@ -0,0 +1,44 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_interface_delete import EventInterfaceDelete
+from discover.fetchers.api.api_access import ApiAccess
+from test.event_based_scan.test_data.event_payload_interface_delete import EVENT_PAYLOAD_INTERFACE_DELETE, NETWORK_DOC, \
+ EVENT_PAYLOAD_REGION, PORT_DOC, ROUTER_DOCUMENT, HOST, VNIC_DOCS
+from test.event_based_scan.test_event import TestEvent
+from utils.util import encode_router_id
+
+
+class TestInterfaceDelete(TestEvent):
+ def test_handle_interface_delete(self):
+ self.values = EVENT_PAYLOAD_INTERFACE_DELETE
+ self.payload = self.values['payload']
+ self.interface = self.payload['router_interface']
+
+ self.port_id = self.interface['port_id']
+ self.host_id = self.values["publisher_id"].replace("network.", "", 1)
+ self.router_id = encode_router_id(self.host_id, self.interface['id'])
+
+ # set document for instance deleting.
+ self.set_item(NETWORK_DOC)
+ self.set_item(PORT_DOC)
+ self.set_item(ROUTER_DOCUMENT)
+ self.set_item(HOST)
+ self.set_item(VNIC_DOCS[0])
+ ApiAccess.regions = EVENT_PAYLOAD_REGION
+
+ # delete interface
+ EventInterfaceDelete().handle(self.env, self.values)
+
+ # assert data
+ router_doc = self.inv.get_by_id(self.env, ROUTER_DOCUMENT['id'])
+ self.assertNotIn(NETWORK_DOC['id'], router_doc['network'])
+
+ self.assert_empty_by_id(PORT_DOC['id'])
+ self.assert_empty_by_id(VNIC_DOCS[0]['id'])
diff --git a/app/test/event_based_scan/test_network_add.py b/app/test/event_based_scan/test_network_add.py
new file mode 100644
index 0000000..08be9e1
--- /dev/null
+++ b/app/test/event_based_scan/test_network_add.py
@@ -0,0 +1,47 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_network_add import EventNetworkAdd
+from test.event_based_scan.test_data.event_payload_network_add import EVENT_PAYLOAD_NETWORK_ADD
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestNetworkAdd(TestEvent):
+
+ def test_handle_network_add(self):
+ self.values = EVENT_PAYLOAD_NETWORK_ADD
+ self.payload = self.values['payload']
+ self.network = self.payload['network']
+ self.network_id = self.network['id']
+ self.item_ids.append(self.network_id)
+
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ if network_document:
+ self.log.info('network document existed already, deleting it first.')
+ self.inv.delete('inventory', {'id': self.network_id})
+
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIsNone(network_document)
+
+ # build network document for adding network
+ project_name = self.values['_context_project_name']
+ project_id = self.values['_context_project_id']
+ parent_id = project_id + '-networks'
+ network_name = self.network['name']
+
+ # add network document
+ EventNetworkAdd().handle(self.env, self.values)
+
+ # check network document
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIsNotNone(network_document)
+ self.assertEqual(network_document["project"], project_name)
+ self.assertEqual(network_document["parent_id"], parent_id)
+ self.assertEqual(network_document["name"], network_name)
+
diff --git a/app/test/event_based_scan/test_network_delete.py b/app/test/event_based_scan/test_network_delete.py
new file mode 100644
index 0000000..3e08af1
--- /dev/null
+++ b/app/test/event_based_scan/test_network_delete.py
@@ -0,0 +1,24 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_network_delete import EventNetworkDelete
+from test.event_based_scan.test_data.event_payload_network_delete import EVENT_PAYLOAD_NETWORK_DELETE, \
+ EVENT_PAYLOAD_NETWORK
+from test.event_based_scan.test_event_delete_base import TestEventDeleteBase
+
+
+class TestNetworkDelete(TestEventDeleteBase):
+
+ def setUp(self):
+ super().setUp()
+ self.values = EVENT_PAYLOAD_NETWORK_DELETE
+ self.set_item_for_deletion(object_type="network", document=EVENT_PAYLOAD_NETWORK)
+
+ def test_handle_network_delete(self):
+ self.handle_delete(handler=EventNetworkDelete())
diff --git a/app/test/event_based_scan/test_network_update.py b/app/test/event_based_scan/test_network_update.py
new file mode 100644
index 0000000..bf9eee4
--- /dev/null
+++ b/app/test/event_based_scan/test_network_update.py
@@ -0,0 +1,33 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_network_update import EventNetworkUpdate
+from test.event_based_scan.test_data.event_payload_network_update import EVENT_PAYLOAD_NETWORK_UPDATE, \
+ NETWORK_DOCUMENT
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestNetworkUpdate(TestEvent):
+
+ def test_handle_network_update(self):
+ self.values = EVENT_PAYLOAD_NETWORK_UPDATE
+ self.payload = self.values['payload']
+ self.network = self.payload['network']
+ name = self.network['name']
+ status = self.network['admin_state_up']
+
+ self.network_id = self.network['id']
+ self.item_ids.append(self.network_id)
+ self.set_item(NETWORK_DOCUMENT)
+
+ EventNetworkUpdate().handle(self.env, self.values)
+
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertEqual(network_document['name'], name)
+ self.assertEqual(network_document['admin_state_up'], status)
diff --git a/app/test/event_based_scan/test_port_add.py b/app/test/event_based_scan/test_port_add.py
new file mode 100644
index 0000000..8bf2553
--- /dev/null
+++ b/app/test/event_based_scan/test_port_add.py
@@ -0,0 +1,75 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+
+from discover.events.event_port_add import EventPortAdd
+from discover.fetchers.api.api_fetch_host_instances import ApiFetchHostInstances
+from discover.fetchers.cli.cli_fetch_instance_vnics import CliFetchInstanceVnics
+from discover.find_links_for_instance_vnics import FindLinksForInstanceVnics
+from discover.find_links_for_vedges import FindLinksForVedges
+from discover.scanner import Scanner
+from test.event_based_scan.test_data.event_payload_port_add import EVENT_PAYLOAD_PORT_INSTANCE_ADD, NETWORK_DOC, \
+ INSTANCE_DOC, INSTANCES_ROOT, VNIC_DOCS, INSTANCE_DOCS
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestPortAdd(TestEvent):
+ def test_handle_port_add(self):
+ self.values = EVENT_PAYLOAD_PORT_INSTANCE_ADD
+ self.payload = self.values['payload']
+ self.port = self.payload['port']
+ self.port_id = self.port['id']
+ self.item_ids.append(self.port_id)
+
+ # prepare data for test
+ self.set_item(NETWORK_DOC)
+ self.set_item(INSTANCE_DOC)
+ self.set_item(INSTANCES_ROOT)
+ self.item_ids.append(VNIC_DOCS[0]['id'])
+
+ # mock methods
+ original_get_instance = ApiFetchHostInstances.get
+ ApiFetchHostInstances.get = MagicMock(return_value=INSTANCE_DOCS)
+
+ original_get_vnic = CliFetchInstanceVnics.get
+ CliFetchInstanceVnics.get = MagicMock(return_value=VNIC_DOCS)
+
+ original_find_link_instance = FindLinksForInstanceVnics.add_links
+ original_find_link_vedge = FindLinksForVedges.add_links
+ original_scan = Scanner.scan_cliques
+
+ FindLinksForInstanceVnics.add_links = MagicMock(return_value=None)
+ FindLinksForVedges.add_links = MagicMock(return_value=None)
+ Scanner.scan_cliques = MagicMock(return_value=None)
+
+ # add network document
+ EventPortAdd().handle(self.env, self.values)
+
+ # check network document
+ port_document = self.inv.get_by_id(self.env, self.port_id)
+ self.assertIsNotNone(port_document)
+ self.assertEqual(port_document["name"], self.port['name'])
+
+ instance = self.inv.get_by_id(self.env, INSTANCE_DOC['id'])
+ self.assertEqual(instance["network_info"][0]['devname'],
+ INSTANCE_DOCS[0]["network_info"][0]['devname'])
+ self.assertEqual(instance["network_info"],
+ INSTANCE_DOCS[0]["network_info"])
+ self.assertEqual(instance["network"], INSTANCE_DOCS[0]["network"])
+
+ vnic = self.inv.get_by_field(self.env, 'vnic', 'mac_address',
+ self.port['mac_address'])
+ self.assertIsNotNone(vnic)
+
+ FindLinksForVedges.add_links = original_find_link_vedge
+ FindLinksForInstanceVnics.add_links = original_find_link_instance
+ Scanner.scan_cliques = original_scan
+ CliFetchInstanceVnics.get = original_get_vnic
+ ApiFetchHostInstances.get = original_get_instance
diff --git a/app/test/event_based_scan/test_port_delete.py b/app/test/event_based_scan/test_port_delete.py
new file mode 100644
index 0000000..78fa1d2
--- /dev/null
+++ b/app/test/event_based_scan/test_port_delete.py
@@ -0,0 +1,47 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+
+from discover.events.event_port_delete import EventPortDelete
+from discover.fetchers.api.api_fetch_host_instances import ApiFetchHostInstances
+from test.event_based_scan.test_data.event_payload_port_delete import EVENT_PAYLOAD_PORT_DELETE, PORT_DOC, VNIC_DOCS, \
+ INSTANCE_DOC, INSTANCE_DOCS
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestPortDelete(TestEvent):
+ def test_handle_port_delete(self):
+ self.values = EVENT_PAYLOAD_PORT_DELETE
+ self.payload = self.values['payload']
+ self.port_id = self.payload['port_id']
+ self.item_ids.append(self.port_id)
+
+ # set port data firstly.
+ self.set_item(PORT_DOC)
+ self.set_item(VNIC_DOCS[0])
+ self.set_item(INSTANCE_DOC)
+
+ # mock methods
+ original_get_instance = ApiFetchHostInstances.get
+ ApiFetchHostInstances.get = MagicMock(return_value=INSTANCE_DOCS)
+ self.item_ids.append(INSTANCE_DOCS[0]['id'])
+
+ # delete port
+ EventPortDelete().handle(self.env, self.values)
+
+ # assert data
+ self.assert_empty_by_id(self.port_id)
+ self.assert_empty_by_id(VNIC_DOCS[0]['id'])
+ instance = self.inv.get_by_id(self.env, INSTANCE_DOC['id'])
+ self.assertEqual(instance['mac_address'], None)
+ self.assertEqual(instance['network'], [])
+ self.assertEqual(instance['network_info'], [])
+
+ ApiFetchHostInstances.get = original_get_instance
diff --git a/app/test/event_based_scan/test_port_update.py b/app/test/event_based_scan/test_port_update.py
new file mode 100644
index 0000000..889bb93
--- /dev/null
+++ b/app/test/event_based_scan/test_port_update.py
@@ -0,0 +1,34 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_port_update import EventPortUpdate
+from test.event_based_scan.test_data.event_payload_port_update import EVENT_PAYLOAD_PORT_UPDATE, PORT_DOCUMENT
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestPortUpdate(TestEvent):
+
+ def test_handle_port_update(self):
+ self.values = EVENT_PAYLOAD_PORT_UPDATE
+ self.payload = self.values['payload']
+ self.port = self.payload['port']
+ self.port_id = self.port['id']
+
+ # set port data firstly.
+ self.inv.set(PORT_DOCUMENT)
+
+ # add network document
+ EventPortUpdate().handle(self.env, self.values)
+
+ # check network document
+ port_document = self.inv.get_by_id(self.env, self.port_id)
+ self.assertIsNotNone(port_document)
+ self.assertEqual(port_document["name"], self.port['name'])
+ self.assertEqual(port_document['admin_state_up'], self.port['admin_state_up'])
+ self.assertEqual(port_document['binding:vnic_type'], self.port['binding:vnic_type'])
diff --git a/app/test/event_based_scan/test_router_add.py b/app/test/event_based_scan/test_router_add.py
new file mode 100644
index 0000000..0a24901
--- /dev/null
+++ b/app/test/event_based_scan/test_router_add.py
@@ -0,0 +1,79 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+
+from discover.events.event_port_add import EventPortAdd
+from discover.events.event_router_add import EventRouterAdd
+from discover.events.event_subnet_add import EventSubnetAdd
+from discover.fetchers.cli.cli_fetch_host_vservice import CliFetchHostVservice
+from test.event_based_scan.test_data.event_payload_router_add import EVENT_PAYLOAD_ROUTER_ADD, ROUTER_DOCUMENT, \
+ HOST_DOC, NETWORK_DOC
+from test.event_based_scan.test_event import TestEvent
+from utils.util import encode_router_id
+
+
+class TestRouterAdd(TestEvent):
+ def test_handle_router_add(self):
+ self.values = EVENT_PAYLOAD_ROUTER_ADD
+ self.payload = self.values['payload']
+ self.router = self.payload['router']
+ self.host_id = self.values["publisher_id"].replace("network.", "", 1)
+ self.router_id = encode_router_id(self.host_id, self.router['id'])
+
+ self.set_item(HOST_DOC)
+ self.host_id = HOST_DOC['id']
+ gateway_info = self.router['external_gateway_info']
+ if gateway_info:
+ self.network_id = self.router['external_gateway_info']['network_id']
+ self.inv.set(NETWORK_DOC)
+
+ original_get_vservice = CliFetchHostVservice.get_vservice
+ CliFetchHostVservice.get_vservice = MagicMock(return_value=ROUTER_DOCUMENT)
+ self.gw_port_id = ROUTER_DOCUMENT['gw_port_id']
+
+ original_add_port = EventSubnetAdd.add_port_document
+ EventSubnetAdd.add_port_document = MagicMock()
+
+ original_add_vnic = EventPortAdd.add_vnic_document
+ EventPortAdd.add_vnic_document = MagicMock()
+
+ handler = EventRouterAdd()
+ handler.update_links_and_cliques = MagicMock()
+
+ handler.handle(self.env, self.values)
+
+ # reset the methods back
+ CliFetchHostVservice.get_vservice = original_get_vservice
+ EventSubnetAdd.add_port_document = original_add_port
+ EventPortAdd.add_vnic_document = original_add_vnic
+
+ # assert router document
+ router_doc = self.inv.get_by_id(self.env, self.router_id)
+ self.assertIsNotNone(router_doc, msg="router_doc not found.")
+ self.assertEqual(ROUTER_DOCUMENT['name'], router_doc['name'])
+ self.assertEqual(ROUTER_DOCUMENT['gw_port_id'], router_doc['gw_port_id'])
+
+ # assert children documents
+ vnics_id = '-'.join(['qrouter', self.router['id'], 'vnics'])
+ vnics_folder = self.inv.get_by_id(self.env, vnics_id)
+ self.assertIsNotNone(vnics_folder, msg="Vnics folder not found.")
+
+ def tearDown(self):
+ self.item_ids = [self.network_id, self.host_id, self.network_id+"-ports", self.gw_port_id,
+ self.router_id+'-vnics', self.router_id]
+ for item_id in self.item_ids:
+ self.inv.delete('inventory', {'id': item_id})
+ item = self.inv.get_by_id(self.env, item_id)
+ self.assertIsNone(item)
+
+ # delete vnics document
+ self.inv.delete('inventory', {'parent_id': self.router_id+'-vnics'})
+ item = self.inv.get_by_field(self.env, 'vnic', 'parent_id', self.router_id+'-vnics', get_single=True)
+ self.assertIsNone(item)
diff --git a/app/test/event_based_scan/test_router_delete.py b/app/test/event_based_scan/test_router_delete.py
new file mode 100644
index 0000000..9d5c13f
--- /dev/null
+++ b/app/test/event_based_scan/test_router_delete.py
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_router_delete import EventRouterDelete
+from test.event_based_scan.test_data.event_payload_router_delete import EVENT_PAYLOAD_ROUTER_DELETE, ROUTER_DOCUMENT
+from test.event_based_scan.test_event_delete_base import TestEventDeleteBase
+
+
+class TestRouterDelete(TestEventDeleteBase):
+
+ def setUp(self):
+ super().setUp()
+ self.values = EVENT_PAYLOAD_ROUTER_DELETE
+ self.set_item_for_deletion(object_type="router", document=ROUTER_DOCUMENT)
+
+ def test_handle_router_delete(self):
+ self.handle_delete(handler=EventRouterDelete())
diff --git a/app/test/event_based_scan/test_router_update.py b/app/test/event_based_scan/test_router_update.py
new file mode 100644
index 0000000..72e8edd
--- /dev/null
+++ b/app/test/event_based_scan/test_router_update.py
@@ -0,0 +1,62 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+
+from discover.events.event_router_update import EventRouterUpdate
+from discover.fetchers.api.api_fetch_port import ApiFetchPort
+from discover.fetchers.cli.cli_fetch_host_vservice import CliFetchHostVservice
+from test.event_based_scan.test_data.event_payload_router_update import EVENT_PAYLOAD_ROUTER_UPDATE, ROUTER_DOCUMENT, \
+ EVENT_PAYLOAD_ROUTER_SET_GATEWAY, EVENT_PAYLOAD_ROUTER_DEL_GATEWAY, ROUTER_VSERVICE, PORTS, NETWORK_DOC, HOST_DOC
+from test.event_based_scan.test_event import TestEvent
+from utils.util import encode_router_id
+
+
+class TestRouterUpdate(TestEvent):
+ def test_handle_router_update(self):
+ for values in [EVENT_PAYLOAD_ROUTER_UPDATE, EVENT_PAYLOAD_ROUTER_SET_GATEWAY, EVENT_PAYLOAD_ROUTER_DEL_GATEWAY]:
+ self.values = values
+ self.payload = self.values['payload']
+ self.router = self.payload['router']
+ host_id = self.values['publisher_id'].replace("network.", "", 1)
+ self.router_id = encode_router_id(host_id, self.router['id'])
+ self.item_ids.append(self.router_id)
+
+ # add document for testing
+ self.set_item(ROUTER_DOCUMENT)
+ self.set_item(PORTS)
+ self.set_item(NETWORK_DOC)
+ self.set_item(HOST_DOC)
+
+ # mock the router document.
+ original_get_vservice = CliFetchHostVservice.get_vservice
+ CliFetchHostVservice.get_vservice = MagicMock(return_value=ROUTER_VSERVICE)
+ self.gw_port_id = ROUTER_DOCUMENT['gw_port_id']
+
+ # mock
+ original_get_port = ApiFetchPort.get
+ ApiFetchPort.get = MagicMock(return_value=[PORTS])
+
+ handler = EventRouterUpdate()
+ handler.handle(self.env, self.values)
+
+ # reset the methods back
+ CliFetchHostVservice.get_vservice = original_get_vservice
+ ApiFetchPort.get = original_get_port
+ # assert router document
+ router_doc = self.inv.get_by_id(self.env, self.router_id)
+ self.assertIsNotNone(router_doc, msg="router_doc not found.")
+ self.assertEqual(self.router['name'], router_doc['name'])
+ self.assertEqual(self.router['admin_state_up'], router_doc['admin_state_up'])
+
+ if self.router['external_gateway_info'] is None:
+ self.assertEqual(router_doc['gw_port_id'], None)
+ self.assertEqual(router_doc['network'], [])
+ else:
+ self.assertIn(self.router['external_gateway_info']['network_id'], router_doc['network'])
diff --git a/app/test/event_based_scan/test_subnet_add.py b/app/test/event_based_scan/test_subnet_add.py
new file mode 100644
index 0000000..a8794ef
--- /dev/null
+++ b/app/test/event_based_scan/test_subnet_add.py
@@ -0,0 +1,68 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+
+from discover.events.event_subnet_add import EventSubnetAdd
+from discover.fetchers.api.api_access import ApiAccess
+from discover.find_links_for_pnics import FindLinksForPnics
+from discover.find_links_for_vservice_vnics import FindLinksForVserviceVnics
+from test.event_based_scan.test_data.event_payload_subnet_add import EVENT_PAYLOAD_SUBNET_ADD,\
+ EVENT_PAYLOAD_REGION, NETWORK_DOC
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestSubnetAdd(TestEvent):
+
+ def test_handle_subnet_add(self):
+ self.values = EVENT_PAYLOAD_SUBNET_ADD
+ self.payload = self.values['payload']
+ self.subnet = self.payload['subnet']
+ self.subnet_id = self.subnet['id']
+ self.network_id = self.subnet['network_id']
+ self.item_ids.append(self.network_id)
+
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ if network_document:
+ # check subnet in network first.
+ self.assertNotIn(self.subnet['cidr'], network_document['cidrs'])
+ else:
+ self.log.info("network document is not found, add it first.")
+ self.set_item(NETWORK_DOC)
+ # check network document
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIsNotNone(network_document)
+
+ # check region data.
+ if not ApiAccess.regions:
+ ApiAccess.regions = EVENT_PAYLOAD_REGION
+
+ # Mock function instead of get children data. They should be test in their unit test.
+ # add subnet document for updating network
+ handler = EventSubnetAdd()
+ handler.add_children_documents = MagicMock()
+
+ original_add_pnic_links = FindLinksForPnics.add_links
+ FindLinksForPnics.add_links = MagicMock()
+
+ original_add_vservice_links = FindLinksForVserviceVnics.add_links
+ FindLinksForVserviceVnics.add_links = MagicMock()
+
+ handler.handle(self.env, self.values)
+
+ # reset the methods back
+ FindLinksForPnics.add_links = original_add_pnic_links
+ FindLinksForVserviceVnics.add_links = original_add_vservice_links
+
+ # check network document
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIn(self.subnet['cidr'], network_document['cidrs'])
+ self.assertIn(self.subnet['name'], network_document['subnets'])
+
+ #tearDown method has been implemented in class testEvent.
diff --git a/app/test/event_based_scan/test_subnet_delete.py b/app/test/event_based_scan/test_subnet_delete.py
new file mode 100644
index 0000000..742b9d9
--- /dev/null
+++ b/app/test/event_based_scan/test_subnet_delete.py
@@ -0,0 +1,54 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_subnet_delete import EventSubnetDelete
+from test.event_based_scan.test_event import TestEvent
+from test.event_based_scan.test_data.event_payload_subnet_delete import EVENT_PAYLOAD_SUBNET_DELETE, \
+ EVENT_PAYLOAD_NETWORK
+
+
+class TestSubnetDelete(TestEvent):
+
+ def test_handle_subnet_delete(self):
+ self.values = EVENT_PAYLOAD_SUBNET_DELETE
+ self.subnet_id = self.values['payload']['subnet_id']
+ self.network_doc = EVENT_PAYLOAD_NETWORK
+ self.network_id = self.network_doc['id']
+ self.item_ids.append(self.network_id)
+
+ self.subnet_name = None
+ self.cidr = None
+
+ for subnet in self.network_doc['subnets'].values():
+ if subnet['id'] == self.subnet_id:
+ self.subnet_name = subnet['name']
+ self.cidr = subnet['cidr']
+ break
+
+ # add document for subnet deleting test.
+ self.set_item(self.network_doc)
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIsNotNone(network_document, "add network document failed")
+
+ # delete subnet
+ EventSubnetDelete().handle(self.env, self.values)
+
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertNotIn(self.subnet_id, network_document['subnet_ids'])
+ self.assertNotIn(self.cidr, network_document['cidrs'])
+ self.assertNotIn(self.subnet_name, network_document['subnets'])
+
+ # assert children documents
+ vservice_dhcp_id = 'qdhcp-' + network_document['id']
+ dhcp_doc = self.inv.get_by_id(self.env, vservice_dhcp_id)
+ self.assertIsNone(dhcp_doc)
+
+ vnic_parent_id = vservice_dhcp_id + '-vnics'
+ vnic = self.inv.get_by_field(self.env, 'vnic', 'parent_id', vnic_parent_id, get_single=True)
+ self.assertIsNone(vnic)
diff --git a/app/test/event_based_scan/test_subnet_update.py b/app/test/event_based_scan/test_subnet_update.py
new file mode 100644
index 0000000..eddfe84
--- /dev/null
+++ b/app/test/event_based_scan/test_subnet_update.py
@@ -0,0 +1,45 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.events.event_subnet_update import EventSubnetUpdate
+from discover.fetchers.api.api_access import ApiAccess
+from test.event_based_scan.test_data.event_payload_subnet_add import \
+ EVENT_PAYLOAD_REGION
+from test.event_based_scan.test_data.event_payload_subnet_update import EVENT_PAYLOAD_SUBNET_UPDATE, NETWORK_DOC
+from test.event_based_scan.test_event import TestEvent
+
+
+class TestSubnetUpdate(TestEvent):
+
+ def test_handle_subnet_add(self):
+ self.values = EVENT_PAYLOAD_SUBNET_UPDATE
+ self.payload = self.values['payload']
+ self.subnet = self.payload['subnet']
+ self.subnet_id = self.subnet['id']
+ self.network_id = self.subnet['network_id']
+ self.item_ids.append(self.network_id)
+
+ #add network document for subnet.
+ self.set_item(NETWORK_DOC)
+
+ # check network document
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIsNotNone(network_document)
+
+ # check region data.
+ if not ApiAccess.regions:
+ ApiAccess.regions = EVENT_PAYLOAD_REGION
+
+ handler = EventSubnetUpdate()
+ handler.handle(self.env, self.values)
+
+ # check network document
+ network_document = self.inv.get_by_id(self.env, self.network_id)
+ self.assertIn(self.subnet['name'], network_document['subnets'])
+ self.assertEqual(self.subnet['gateway_ip'], network_document['subnets'][self.subnet['name']]['gateway_ip'])
diff --git a/app/test/fetch/__init__.py b/app/test/fetch/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/api_fetch/__init__.py b/app/test/fetch/api_fetch/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/api_fetch/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/api_fetch/test_api_access.py b/app/test/fetch/api_fetch/test_api_access.py
new file mode 100644
index 0000000..e4767b7
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_access.py
@@ -0,0 +1,142 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import patch, MagicMock
+from discover.fetchers.api.api_access import ApiAccess
+from test.fetch.api_fetch.test_data.api_access import *
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.regions import REGIONS
+
+
+class TestApiAccess(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.api_access = ApiAccess()
+ self.set_regions_for_fetcher(self.api_access)
+
+ def test_parse_time_without_dot_in_time(self):
+ time = self.api_access.parse_time(TIME_WITHOUT_DOT)
+ self.assertNotEqual(time, None, "Can't parse the time without dot")
+
+ def test_parse_time_with_dot_in_time(self):
+ time = self.api_access.parse_time(TIME_WITH_DOT)
+ self.assertNotEqual(time, None, "Can't parse the time with dot")
+
+ def test_parse_illegal_time(self):
+ time = self.api_access.parse_time(ILLEGAL_TIME)
+ self.assertEqual(time, None, "Can't get None when the time format is wrong")
+
+ def test_get_existing_token(self):
+ self.api_access.tokens = VALID_TOKENS
+ token = self.api_access.get_existing_token(PROJECT)
+ self.assertNotEqual(token, VALID_TOKENS[PROJECT], "Can't get existing token")
+
+ def test_get_nonexistent_token(self):
+ self.api_access.tokens = EMPTY_TOKENS
+ token = self.api_access.get_existing_token(TEST_PROJECT)
+ self.assertEqual(token, None, "Can't get None when the token doesn't " +
+ "exist in tokens")
+
+ @patch("httplib2.Http.request")
+ def test_v2_auth(self, mock_request):
+ self.api_access.get_existing_token = MagicMock(return_value=None)
+ # mock authentication info from OpenStack Api
+ mock_request.return_value = (RESPONSE, CORRECT_AUTH_CONTENT)
+ token_details = self.api_access.v2_auth(TEST_PROJECT, TEST_HEADER, TEST_BODY)
+ self.assertNotEqual(token_details, None, "Can't get the token details")
+
+ @patch("httplib2.Http.request")
+ def test_v2_auth_with_error_content(self, mock_request):
+ self.api_access.get_existing_token = MagicMock(return_value=None)
+ # authentication content from OpenStack Api will be incorrect
+ mock_request.return_value = (RESPONSE, ERROR_AUTH_CONTENT)
+ token_details = self.api_access.v2_auth(TEST_PROJECT, TEST_HEADER, TEST_BODY)
+ self.assertIs(token_details, None, "Can't get None when the content is wrong")
+
+ @patch("httplib2.Http.request")
+ def test_v2_auth_with_error_token(self, mock_request):
+ # authentication info from OpenStack Api will not contain token info
+ mock_request.return_value = (RESPONSE, ERROR_TOKEN_CONTENT)
+ token_details = self.api_access.v2_auth(TEST_PROJECT, TEST_HEADER, TEST_BODY)
+ self.assertIs(token_details, None, "Can't get None when the content " +
+ "doesn't contain any token info")
+
+ @patch("httplib2.Http.request")
+ def test_v2_auth_with_error_expiry_time(self, mock_request):
+ mock_request.return_value = (RESPONSE, CORRECT_AUTH_CONTENT)
+
+ # store original parse_time method
+ original_method = self.api_access.parse_time
+ # the time will not be parsed
+ self.api_access.parse_time = MagicMock(return_value=None)
+
+ token_details = self.api_access.v2_auth(TEST_PROJECT, TEST_HEADER, TEST_BODY)
+ # reset original parse_time method
+ self.api_access.parse_time = original_method
+
+ self.assertIs(token_details, None, "Can't get None when the time in token " +
+ "can't be parsed")
+
+ @patch("httplib2.Http.request")
+ def test_v2_auth_pwd(self, mock_request):
+ # mock the authentication info from OpenStack Api
+ mock_request.return_value = (RESPONSE, CORRECT_AUTH_CONTENT)
+ token = self.api_access.v2_auth_pwd(PROJECT)
+ self.assertNotEqual(token, None, "Can't get token")
+
+ @patch("httplib2.Http.request")
+ def test_get_url(self, mock_request):
+ mock_request.return_value = (RESPONSE, GET_CONTENT)
+ result = self.api_access.get_url(TEST_URL, TEST_HEADER)
+ # check whether it returns content message when the response is correct
+ self.assertNotIn("status", result, "Can't get content when the " +
+ "response is correct")
+
+ @patch("httplib2.Http.request")
+ def test_get_url_with_error_response(self, mock_request):
+ # the response will be wrong
+ mock_request.return_value = (ERROR_RESPONSE, None)
+ result = self.api_access.get_url(TEST_URL, TEST_HEADER)
+ self.assertNotEqual(result, None, "Can't get response message " +
+ "when the response status is not 200")
+
+ def test_get_region_url(self):
+ region_url = self.api_access.get_region_url(REGION_NAME, SERVICE_NAME)
+
+ self.assertNotEqual(region_url, None, "Can't get region url")
+
+ def test_get_region_url_with_wrong_region_name(self):
+ # error region name doesn't exist in the regions info
+ region_url = self.api_access.get_region_url(ERROR_REGION_NAME, "")
+ self.assertIs(region_url, None, "Can't get None with the region " +
+ "name is wrong")
+
+ def test_get_region_url_without_service_endpoint(self):
+ # error service doesn't exist in region service endpoints
+ region_url = self.api_access.get_region_url(REGION_NAME, ERROR_SERVICE_NAME)
+ self.assertIs(region_url, None, "Can't get None with wrong service name")
+
+ def test_region_url_nover(self):
+ # mock return value of get_region_url, which has something starting from v2
+ self.api_access.get_region_url = MagicMock(return_value=REGION_URL)
+ region_url = self.api_access.get_region_url_nover(REGION_NAME, SERVICE_NAME)
+ # get_region_nover will remove everything from v2
+ self.assertNotIn("v2", region_url, "Can't get region url without v2 info")
+
+ def test_get_service_region_endpoints(self):
+ region = REGIONS[REGION_NAME]
+ result = self.api_access.get_service_region_endpoints(region, SERVICE_NAME)
+ self.assertNotEqual(result, None, "Can't get service endpoint")
+
+ def test_get_service_region_endpoints_with_nonexistent_service(self):
+ region = REGIONS[REGION_NAME]
+ result = self.api_access.get_service_region_endpoints(region, ERROR_SERVICE_NAME)
+ self.assertIs(result, None, "Can't get None when the service name " +
+ "doesn't exist in region's services")
diff --git a/app/test/fetch/api_fetch/test_api_fetch_availability_zone.py b/app/test/fetch/api_fetch/test_api_fetch_availability_zone.py
new file mode 100644
index 0000000..f32be36
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_availability_zone.py
@@ -0,0 +1,72 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.api.api_fetch_availability_zones import ApiFetchAvailabilityZones
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_availability_zones import *
+from unittest.mock import MagicMock
+from test.fetch.api_fetch.test_data.token import TOKEN
+
+
+class TestApiFetchAvailabilityZones(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ ApiFetchAvailabilityZones.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.fetcher = ApiFetchAvailabilityZones()
+ self.set_regions_for_fetcher(self.fetcher)
+
+ def test_get_for_region(self):
+ # mock the endpoint url
+ self.fetcher.get_region_url_nover = MagicMock(return_value=ENDPOINT)
+ # mock the response from OpenStack Api
+ self.fetcher.get_url = MagicMock(return_value=AVAILABILITY_ZONE_RESPONSE)
+
+ result = self.fetcher.get_for_region(PROJECT, REGION_NAME, TOKEN)
+ self.assertNotEqual(result, [], "Can't get availability zone info")
+
+ def test_get_for_region_with_wrong_response(self):
+ # mock the endpoint url
+ self.fetcher.get_region_url_nover = MagicMock(return_value=ENDPOINT)
+ # mock the wrong response from OpenStack Api
+ self.fetcher.get_url = MagicMock(return_value=WRONG_RESPONSE)
+
+ result = self.fetcher.get_for_region(PROJECT, REGION_NAME, TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the response is wrong")
+
+ def test_get_for_region_without_avz_response(self):
+ # mock the endpoint url
+ self.fetcher.get_region_url_nover = MagicMock(return_value=ENDPOINT)
+ # mock the response from OpenStack Api
+ # the response doesn't contain availability zone info
+ self.fetcher.get_url = MagicMock(return_value=RESPONSE_WITHOUT_AVAILABILITY_ZONE)
+
+ result = self.fetcher.get_for_region(PROJECT, REGION_NAME, TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the response doesn't " +
+ "contain availability zone")
+
+ def test_get(self):
+ # store original get_for_region method
+ original_method = self.fetcher.get_for_region
+ # mock the result from get_for_region method
+ self.fetcher.get_for_region = MagicMock(return_value=GET_REGION_RESULT)
+
+ result = self.fetcher.get(PROJECT)
+
+ # reset get_for_region method
+ self.fetcher.get_for_region = original_method
+
+ self.assertNotEqual(result, [], "Can't get availability zone info")
+
+ def test_get_without_token(self):
+ # mock the empty token
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=None)
+ result = self.fetcher.get(PROJECT)
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the token is invalid")
diff --git a/app/test/fetch/api_fetch/test_api_fetch_host_instances.py b/app/test/fetch/api_fetch/test_api_fetch_host_instances.py
new file mode 100644
index 0000000..c1c7b6e
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_host_instances.py
@@ -0,0 +1,83 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.api.api_fetch_host_instances import ApiFetchHostInstances
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_host_instances import *
+from test.fetch.api_fetch.test_data.token import TOKEN
+from unittest.mock import MagicMock
+
+
+class TestApiFetchHostInstances(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ ApiFetchHostInstances.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.fetcher = ApiFetchHostInstances()
+ self.set_regions_for_fetcher(self.fetcher)
+
+ def test_get_projects(self):
+ # mock the projects got from the database
+ self.fetcher.inv.get = MagicMock(return_value=PROJECT_LIST)
+
+ self.fetcher.get_projects()
+ self.assertNotEqual(self.fetcher.projects, None, "Can't get projects info")
+
+ def test_get_instances_from_api(self):
+ self.fetcher.inv.get = MagicMock(return_value=PROJECT_LIST)
+ # mock the response from the OpenStack Api
+ self.fetcher.get_url = MagicMock(return_value=GET_SERVERS_RESPONSE)
+
+ result = self.fetcher.get_instances_from_api(HOST_NAME)
+ self.assertEqual(result, GET_INSTANCES_FROM_API, "Can't get correct " +
+ "instances info")
+
+ def test_get_instances_from_api_with_wrong_auth(self):
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=None)
+
+ result = self.fetcher.get_instances_from_api(HOST_NAME)
+ self.assertEqual(result, [], "Can't get [] when the token is invalid")
+
+ def test_get_instances_from_api_without_hypervisors_in_res(self):
+ # mock the response without hypervisors info from OpenStack Api
+ self.fetcher.get_url = MagicMock(return_value=RESPONSE_WITHOUT_HYPERVISORS)
+
+ result = self.fetcher.get_instances_from_api(HOST_NAME)
+ self.assertEqual(result, [], "Can't get [] when the response doesn't " +
+ "contain hypervisors info")
+
+ def test_get_instances_from_api_without_servers_in_res(self):
+ # mock the response without servers info from OpenStack Api
+ self.fetcher.get_url = MagicMock(return_value=RESPONSE_WITHOUT_SERVERS)
+
+ result = self.fetcher.get_instances_from_api(HOST_NAME)
+ self.assertEqual(result, [], "Can't get [] when the response doesn't " +
+ "contain servers info")
+
+ def test_get(self):
+ self.fetcher.inv.get = MagicMock(return_value=PROJECT_LIST)
+ self.fetcher.inv.get_by_id = MagicMock(return_value=HOST)
+
+ original_method = self.fetcher.get_instances_from_api
+ self.fetcher.get_instances_from_api = MagicMock(return_value=
+ GET_INSTANCES_FROM_API)
+
+ self.fetcher.db_fetcher.get_instance_data = MagicMock()
+ result = self.fetcher.get(INSTANCE_FOLDER_ID)
+ self.assertNotEqual(result, [], "Can't get instances info")
+
+ self.fetcher.get_instances_from_api = original_method
+
+ def test_get_with_non_compute_node(self):
+ self.fetcher.inv.get = MagicMock(return_value=PROJECT_LIST)
+ self.fetcher.inv.get_by_id = MagicMock(return_value=NON_COMPUTE_HOST)
+
+ result = self.fetcher.get(INSTANCE_FOLDER_ID)
+ self.assertEqual(result, [], "Can't get [] when the host is " +
+ "not compute node")
diff --git a/app/test/fetch/api_fetch/test_api_fetch_networks.py b/app/test/fetch/api_fetch/test_api_fetch_networks.py
new file mode 100644
index 0000000..1dc74ce
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_networks.py
@@ -0,0 +1,65 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+from discover.fetchers.api.api_fetch_networks import ApiFetchNetworks
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_networks import *
+from test.fetch.api_fetch.test_data.token import TOKEN
+
+
+class TestApiFetchNetworks(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ ApiFetchNetworks.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.fetcher = ApiFetchNetworks()
+ self.set_regions_for_fetcher(self.fetcher)
+
+ def test_get_networks(self):
+ self.fetcher.get_region_url_nover = MagicMock(return_value=ENDPOINT)
+ self.fetcher.get_url = MagicMock(side_effect=[NETWORKS_RESPONSE,
+ SUBNETS_RESPONSE])
+ self.fetcher.inv.get_by_id = MagicMock(return_value=PROJECT)
+ result = self.fetcher.get_networks(REGION_NAME, TOKEN)
+ self.assertEqual(result, NETWORKS_RESULT, "Can't get networks info")
+
+ def test_get_networks_with_wrong_networks_response(self):
+ self.fetcher.get_region_url_nover = MagicMock(return_value=ENDPOINT)
+ self.fetcher.get_url = MagicMock(return_value=WRONG_NETWORK_RESPONSE)
+
+ result = self.fetcher.get_networks(REGION_NAME, TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the networks " +
+ "response is wrong")
+
+ def test_get_networks_with_wrong_subnet_response(self):
+ self.fetcher.get_region_url_nover = MagicMock(return_value=ENDPOINT)
+ self.fetcher.get_url = MagicMock(side_effect=[NETWORKS_RESPONSE,
+ WRONG_SUBNETS_RESPONSE])
+ self.fetcher.inv.get_by_id = MagicMock(return_value=PROJECT)
+
+ result = self.fetcher.get_networks(REGION_NAME, TOKEN)
+
+ self.assertNotEqual(result, [], "Can't get networks info when the " +
+ "subnet response is wrong")
+
+ def test_get(self):
+ original_method = self.fetcher.get_networks
+ self.fetcher.get_networks = MagicMock(return_value=NETWORKS_RESULT)
+ result = self.fetcher.get(REGION_NAME)
+
+ self.fetcher.get_networks = original_method
+ self.assertEqual(result, NETWORKS_RESULT, "Can't get region networks info")
+
+ def test_get_with_wrong_token(self):
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=None)
+ result = self.fetcher.get(REGION_NAME)
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the " +
+ "token is invalid")
diff --git a/app/test/fetch/api_fetch/test_api_fetch_ports.py b/app/test/fetch/api_fetch/test_api_fetch_ports.py
new file mode 100644
index 0000000..ad79757
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_ports.py
@@ -0,0 +1,89 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.api.api_fetch_ports import ApiFetchPorts
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_ports import *
+from test.fetch.api_fetch.test_data.token import TOKEN
+from unittest.mock import MagicMock
+
+
+class TestApiFetchPorts(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ ApiFetchPorts.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.fetcher = ApiFetchPorts()
+ self.set_regions_for_fetcher(self.fetcher)
+
+ def check_get_ports_for_region_result_is_correct(self, network,
+ tenant,
+ port_response,
+ expected_result,
+ error_msg):
+ self.fetcher.get_region_url = MagicMock(return_value=ENDPOINT)
+ self.fetcher.get_url = MagicMock(return_value=port_response)
+ self.fetcher.inv.get_by_id = MagicMock(side_effect=[network, tenant])
+
+ result = self.fetcher.get_ports_for_region(REGION_NAME, TOKEN)
+ self.assertEqual(result, expected_result, error_msg)
+
+ def test_get_ports_for_region(self):
+ test_cases = [
+ {
+ "network": NETWORK,
+ "tenant": None,
+ "port_response": PORTS_RESPONSE,
+ "expected_result": PORTS_RESULT_WITH_NET,
+ "error_msg": "Can't get correct ports info "
+ "when network of the port exists"
+ },
+ {
+ "network": None,
+ "tenant": None,
+ "port_response": PORTS_RESPONSE,
+ "expected_result": PORTS_RESULT_WITHOUT_NET,
+ "error_msg": "Can't get correct ports info "
+ "when network of the port doesn't exists"
+ },
+ {
+ "network": NETWORK,
+ "tenant": TENANT,
+ "port_response": PORTS_RESPONSE,
+ "expected_result": PORTS_RESULT_WITH_PROJECT,
+ "error_msg": "Can't get correct ports info "
+ "when project of the port exists"
+ },
+ {
+ "network": None,
+ "tenant": None,
+ "port_response": ERROR_PORTS_RESPONSE,
+ "expected_result": [],
+ "error_msg": "Can't get [] when ports response is wrong"
+ },
+ ]
+ for test_case in test_cases:
+ self.check_get_ports_for_region_result_is_correct(test_case["network"],
+ test_case["tenant"],
+ test_case["port_response"],
+ test_case["expected_result"],
+ test_case["error_msg"])
+
+ def test_get(self):
+ original_method = self.fetcher.get_ports_for_region
+ self.fetcher.get_ports_for_region = MagicMock(return_value=PORTS_RESULT_WITH_NET)
+ result = self.fetcher.get(REGION_NAME)
+ self.fetcher.get_ports_for_region = original_method
+ self.assertEqual(result, PORTS_RESULT_WITH_NET, "Can't get correct ports info")
+
+ def test_get_with_wrong_token(self):
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=None)
+ result = self.fetcher.get(REGION_NAME)
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the token is invalid")
diff --git a/app/test/fetch/api_fetch/test_api_fetch_project_hosts.py b/app/test/fetch/api_fetch/test_api_fetch_project_hosts.py
new file mode 100644
index 0000000..7cedf67
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_project_hosts.py
@@ -0,0 +1,137 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+from discover.fetchers.api.api_fetch_project_hosts import ApiFetchProjectHosts
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_host_project_hosts import *
+from test.fetch.api_fetch.test_data.token import TOKEN
+from test.fetch.api_fetch.test_data.regions import REGIONS
+
+
+class TestApiFetchProjectHosts(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ ApiFetchProjectHosts.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.fetcher = ApiFetchProjectHosts()
+ self.set_regions_for_fetcher(self.fetcher)
+ self.region = REGIONS[REGION_NAME]
+
+ def test_add_host_type_with_nonexistent_type(self):
+ # clear host type
+ HOST_DOC["host_type"] = []
+ self.fetcher.add_host_type(HOST_DOC, NONEXISTENT_TYPE, HOST_ZONE)
+ self.assertIn(NONEXISTENT_TYPE, HOST_DOC["host_type"], "Can't put nonexistent " +
+ "type in host_type")
+
+ def test_add_host_type_with_existent_host_type(self):
+ # add nonexistent host type to host type
+ HOST_DOC["host_type"] = [NONEXISTENT_TYPE]
+ # try to add existing host type
+ self.fetcher.add_host_type(HOST_DOC, NONEXISTENT_TYPE, HOST_ZONE)
+ self.assertEqual(len(HOST_DOC['host_type']), 1, "Add duplicate host type")
+
+ def test_add_compute_host_type(self):
+ HOST_DOC['host_type'] = []
+ # clear zone
+ HOST_DOC['zone'] = None
+ # add compute host type
+ self.fetcher.add_host_type(HOST_DOC, COMPUTE_TYPE, HOST_ZONE)
+ # for compute host type, zone information will be added
+ self.assertEqual(HOST_DOC['zone'], HOST_ZONE, "Can't update zone " +
+ "name for compute node")
+ self.assertEqual(HOST_DOC['parent_id'], HOST_ZONE, "Can't update parent_id " +
+ "for compute node")
+
+ def test_fetch_compute_node_ip_address(self):
+ # mock ip address information fetched from DB
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=IP_ADDRESS_RESPONSE)
+
+ self.fetcher.fetch_compute_node_ip_address(HOST_TO_BE_FETCHED_IP,
+ HOST_TO_BE_FETCHED_IP["host"])
+ self.assertIn("ip_address", HOST_TO_BE_FETCHED_IP, "Can't update ip address " +
+ "for the compute host")
+
+ def test_fetch_network_node_details(self):
+ # mock NETWORKS_DETAILS_RESPONSE fetched from DB
+ self.fetcher.get_objects_list = MagicMock(return_value=NETWORKS_DETAILS_RESPONSE)
+
+ self.fetcher.fetch_network_node_details(HOSTS_TO_BE_FETCHED_NETWORK_DETAILS)
+ # get the network node document from HOSTS
+ NETWORK_NODE_DOC = [doc for doc in HOSTS_TO_BE_FETCHED_NETWORK_DETAILS
+ if doc['host'] == HOST_NAME][0]
+ # check if the network node document has been updated
+ self.assertIn("Network", NETWORK_NODE_DOC['host_type'], "Can't put Network in " +
+ "the network node host_type")
+ self.assertIn("config", NETWORK_NODE_DOC, "Can't put config in the network node")
+
+ def test_get_host_details(self):
+ # test node have nova-conductor attribute, controller type will be added
+ result = self.fetcher.get_host_details(AVAILABILITY_ZONE, HOST_NAME)
+ self.assertIn("Controller", result['host_type'], "Can't put controller type " +
+ "in the compute node host_type")
+
+ def test_get_hosts_from_az(self):
+ result = self.fetcher.get_hosts_from_az(AVAILABILITY_ZONE)
+ self.assertNotEqual(result, [], "Can't get hosts information from "
+ "availability zone")
+
+ def test_get_for_region(self):
+ # mock region url for nova node
+ self.fetcher.get_region_url = MagicMock(return_value=REGION_URL)
+ # mock the response from OpenStack Api
+ side_effect = [AVAILABILITY_ZONE_RESPONSE, HYPERVISORS_RESPONSE]
+ self.fetcher.get_url = MagicMock(side_effect=side_effect)
+
+ result = self.fetcher.get_for_region(self.region, TOKEN)
+ self.assertNotEqual(result, [], "Can't get hosts information for region")
+
+ def test_get_for_region_without_token(self):
+ self.fetcher.get_region_url = MagicMock(return_value=REGION_URL)
+ result = self.fetcher.get_for_region(self.region, None)
+ self.assertEqual(result, [], "Can't get [] when the token is invalid")
+
+ def test_get_for_region_with_error_availability_response(self):
+ self.fetcher.get_region_url = MagicMock(return_value=REGION_URL)
+ # mock error availability zone response from OpenStack Api
+ side_effect = [AVAILABILITY_ERROR_RESPONSE, None]
+ self.fetcher.get_url = MagicMock(side_effect=side_effect)
+
+ result = self.fetcher.get_for_region(self.region, TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the response is wrong")
+
+ def test_get_for_region_with_error_hypervisors_response(self):
+ self.fetcher.get_region_url = MagicMock(return_value=REGION_URL)
+ # mock error hypervisors response from OpenStack Api
+ side_effect = [AVAILABILITY_ZONE_RESPONSE, HYPERVISORS_ERROR_RESPONSE]
+ self.fetcher.get_url = MagicMock(side_effect=side_effect)
+
+ result = self.fetcher.get_for_region(self.region, TOKEN)
+ self.assertNotEqual(result, [], "Can't get hosts information when " +
+ "the hypervisors response is wrong")
+
+ def test_get(self):
+ original_method = self.fetcher.get_for_region
+ self.fetcher.get_for_region = MagicMock(return_value=GET_FOR_REGION_INFO)
+
+ result = self.fetcher.get(PROJECT_NAME)
+
+ self.fetcher.get_for_region = original_method
+
+ self.assertNotEqual(result, [], "Can't get hosts info for the project")
+
+ def test_get_with_wrong_project_name(self):
+ result = self.fetcher.get(TEST_PROJECT_NAME)
+ self.assertEqual(result, [], "Can't get [] when the project name is not admin")
+
+ def test_get_with_wrong_token(self):
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=[])
+ result = self.fetcher.get(PROJECT_NAME)
+ self.assertEqual(result, [], "Can't get [] when the token is invalid")
diff --git a/app/test/fetch/api_fetch/test_api_fetch_projects.py b/app/test/fetch/api_fetch/test_api_fetch_projects.py
new file mode 100644
index 0000000..1db4237
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_projects.py
@@ -0,0 +1,120 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from unittest.mock import MagicMock
+from discover.fetchers.api.api_fetch_projects import ApiFetchProjects
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_projects import *
+from test.fetch.api_fetch.test_data.regions import REGIONS
+from test.fetch.api_fetch.test_data.token import TOKEN
+
+
+class TestApiFetchProjects(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ ApiFetchProjects.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.fetcher = ApiFetchProjects()
+ self.set_regions_for_fetcher(self.fetcher)
+ self.region = REGIONS[REGION_NAME]
+ self.fetcher.get_region_url_nover = MagicMock(return_value=REGION_URL_NOVER)
+
+ def test_get_for_region(self):
+ # mock request endpoint
+ self.fetcher.get_region_url_nover = MagicMock(return_value=REGION_URL_NOVER)
+ self.fetcher.get_url = MagicMock(return_value=REGION_RESPONSE)
+
+ result = self.fetcher.get_for_region(self.region, TOKEN)
+ self.assertEqual(result, REGION_RESULT, "Can't get correct projects info")
+
+ # TODO does this test case make sense?
+ def test_get_for_region_with_error_region_response(self):
+ self.fetcher.get_region_url_nover = MagicMock(return_value=REGION_URL_NOVER)
+ self.fetcher.get_url = MagicMock(return_value=REGION_ERROR_RESPONSE)
+
+ result = self.fetcher.get_for_region(self.region, TOKEN)
+ self.assertEqual(result, [], "Can't get [] when the " +
+ "region response is wrong")
+
+ def test_get_projects_for_api_user(self):
+ # mock the responses from OpenStack Api
+ self.fetcher.get_url = MagicMock(return_value=PROJECTS_CORRECT_RESPONSE)
+
+ result = self.fetcher.get_projects_for_api_user(self.region, TOKEN)
+ self.assertEqual(result, PROJECT_RESULT, "Can't get correct " +
+ "projects info for api user")
+
+ def test_get_projects_for_api_user_without_projects_response(self):
+ # the projects info from OpenStack Api will be None
+ self.fetcher.get_url = MagicMock(return_value=
+ PROJECTS_RESPONSE_WITHOUT_PROJECTS)
+
+ result = self.fetcher.get_projects_for_api_user(self.region, TOKEN)
+ self.assertIs(result, None, "Can't get None when the project " +
+ "response doesn't contain projects info")
+
+ def check_get_result(self, projects_for_api_user,
+ region_result,
+ token,
+ expected_result, error_msg):
+ self.fetcher.get_projects_for_api_user = MagicMock(return_value=
+ projects_for_api_user)
+ original_method = self.fetcher.get_for_region
+ # mock
+ self.fetcher.get_for_region = MagicMock(return_value=region_result)
+ self.fetcher.v2_auth_pwd = MagicMock(return_value=token)
+
+ result = self.fetcher.get(PROJECT_ID)
+
+ self.fetcher.get_for_region = original_method
+ self.assertEqual(result, expected_result, error_msg)
+
+ def test_get(self):
+ # test get method with different test cases
+ test_cases = [
+ {
+ "projects": PROJECT_RESULT,
+ "regions": REGION_RESULT,
+ "token": TOKEN,
+ "expected_result": REGION_RESULT,
+ "err_msg": "Can't get correct project result"
+ },
+ {
+ "projects": PROJECT_RESULT,
+ "regions": REGION_RESULT_WITH_NON_USER_PROJECT,
+ "token": TOKEN,
+ "expected_result": REGION_RESULT,
+ "err_msg": "Can't get correct project result" +
+ "when the region result contains project " +
+ "that doesn't belong to the user"
+ },
+ {
+ "projects": PROJECT_RESULT,
+ "regions": REGION_RESULT,
+ "token": None,
+ "expected_result": [],
+ "err_msg": "Can't get [] when the token is invalid"
+ },
+ {
+ "projects": None,
+ "regions": REGION_RESULT,
+ "token": TOKEN,
+ "expected_result": REGION_RESULT,
+ "err_msg": "Can't get the region " +
+ "result if the projects " +
+ "for the user doesn't exist"
+ }
+ ]
+
+ for test_case in test_cases:
+ self.check_get_result(test_case["projects"],
+ test_case["regions"],
+ test_case["token"],
+ test_case["expected_result"],
+ test_case["err_msg"])
diff --git a/app/test/fetch/api_fetch/test_api_fetch_regions.py b/app/test/fetch/api_fetch/test_api_fetch_regions.py
new file mode 100644
index 0000000..1ff7999
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_api_fetch_regions.py
@@ -0,0 +1,41 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.api.api_access import ApiAccess
+from discover.fetchers.api.api_fetch_regions import ApiFetchRegions
+from test.fetch.test_fetch import TestFetch
+from test.fetch.api_fetch.test_data.api_fetch_regions import *
+from test.fetch.api_fetch.test_data.token import TOKEN
+from unittest.mock import MagicMock
+
+
+class TestApiFetchRegions(TestFetch):
+
+ def setUp(self):
+ ApiFetchRegions.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.configure_environment()
+
+ def test_get(self):
+ fetcher = ApiFetchRegions()
+ fetcher.set_env(ENV)
+
+ ApiAccess.auth_response = AUTH_RESPONSE
+ ret = fetcher.get("test_id")
+ self.assertEqual(ret, REGIONS_RESULT,
+ "Can't get correct regions information")
+
+ def test_get_without_token(self):
+ fetcher = ApiFetchRegions()
+ fetcher.v2_auth_pwd = MagicMock(return_value=[])
+ fetcher.set_env(ENV)
+
+ ret = fetcher.get("test_id")
+
+ ApiFetchRegions.v2_auth_pwd = MagicMock(return_value=TOKEN)
+ self.assertEqual(ret, [], "Can't get [] when the token is invalid")
diff --git a/app/test/fetch/api_fetch/test_data/__init__.py b/app/test/fetch/api_fetch/test_data/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/api_fetch/test_data/api_access.py b/app/test/fetch/api_fetch/test_data/api_access.py
new file mode 100644
index 0000000..2181c48
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_access.py
@@ -0,0 +1,55 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from datetime import datetime, timedelta
+
+
+TIME_WITH_DOT = "2016-10-19T23:21:09.418406Z"
+TIME_WITHOUT_DOT = "2016-10-19T23:21:09Z"
+ILLEGAL_TIME = "23243423"
+TEST_PROJECT = "test"
+PROJECT = "admin"
+TEST_URL = "test_url"
+TEST_HEADER = "test_headers"
+TEST_BODY = "test_body"
+
+RESPONSE = {
+ 'server': 'Apache',
+ 'vary': 'X-Auth-Token',
+ 'content-type': 'application/json',
+ 'date': 'Wed, 19 Oct 2016 23:15:36 GMT',
+ 'content-length': '4876',
+ 'x-openstack-request-id': 'req-01cda259-7f60-4440-99a0-508fed90f815',
+ 'connection': 'close',
+ 'status': '200'
+}
+ERROR_RESPONSE = {
+ 'connection': 'close',
+ 'status': '400'
+}
+GET_CONTENT = b'{"text":"test"}'
+CORRECT_AUTH_CONTENT = b'{"access": {"token": {"issued_at": "2016-10-21T23:49:50.000000Z", "expires": "2016-10-22T00:49:50.445603Z", "id": "gAAAAABYCqme1l0qCm6mi3jON4ElweTkhZjGXZ_bYuxLHZGGXgO3T_JLnxKJ7KbK4xA8KjQ-DQe2trDncKQA0M-yeX167wT0xO_rjqqcCA19JV-EeXFfx7QOukkt8eC4pfK1r8Dc_kvBc-bwAemjZ1IvPGu5Nd2f0ktGWre0Qqzbg9QGtCEJUe8", "tenant": {"is_domain": false, "description": "admin tenant", "enabled": true, "id": "8c1751e0ce714736a63fee3c776164da", "parent_id": null, "name": "admin"}, "audit_ids": ["8BvzDPpyRBmeJho-FzKuGA"]}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da", "region": "RegionOne", "internalURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da", "id": "274cbbd9fd6d4311b78e78dd3a1df51f", "publicURL": "http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da"}], "endpoints_links": [], "type": "compute", "name": "nova"}, {"endpoints": [{"adminURL": "http://192.168.0.2:9696", "region": "RegionOne", "internalURL": "http://192.168.0.2:9696", "id": "8dc28584da224c4b9671171ead3c982a", "publicURL": "http://172.16.0.3:9696"}], "endpoints_links": [], "type": "network", "name": "neutron"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da", "region": "RegionOne", "internalURL": "http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da", "id": "2c30937688e944889db4a64fab6816e6", "publicURL": "http://172.16.0.3:8776/v2/8c1751e0ce714736a63fee3c776164da"}], "endpoints_links": [], "type": "volumev2", "name": "cinderv2"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8774/v3", "region": "RegionOne", "internalURL": "http://192.168.0.2:8774/v3", "id": "1df917160dfb4ce5b469764fde22b3ab", "publicURL": "http://172.16.0.3:8774/v3"}], "endpoints_links": [], "type": "computev3", "name": "novav3"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8080", "region": "RegionOne", "internalURL": "http://192.168.0.2:8080", "id": "4f655c8f2bef46a0a7ba4a20bba53666", "publicURL": "http://172.16.0.3:8080"}], "endpoints_links": [], "type": "s3", "name": "swift_s3"}, {"endpoints": [{"adminURL": "http://192.168.0.2:9292", "region": "RegionOne", "internalURL": "http://192.168.0.2:9292", "id": "475c6c77a94e4e63a5a0f0e767f697a8", "publicURL": "http://172.16.0.3:9292"}], "endpoints_links": [], "type": "image", "name": "glance"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8777", "region": "RegionOne", "internalURL": "http://192.168.0.2:8777", "id": "617177a3dcb64560a5a79ab0a91a7225", "publicURL": "http://172.16.0.3:8777"}], "endpoints_links": [], "type": "metering", "name": "ceilometer"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8000/v1", "region": "RegionOne", "internalURL": "http://192.168.0.2:8000/v1", "id": "0f04ec6ed49f4940822161bf677bdfb2", "publicURL": "http://172.16.0.3:8000/v1"}], "endpoints_links": [], "type": "cloudformation", "name": "heat-cfn"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da", "region": "RegionOne", "internalURL": "http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da", "id": "05643f2cf9094265b432376571851841", "publicURL": "http://172.16.0.3:8776/v1/8c1751e0ce714736a63fee3c776164da"}], "endpoints_links": [], "type": "volume", "name": "cinder"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8773/services/Admin", "region": "RegionOne", "internalURL": "http://192.168.0.2:8773/services/Cloud", "id": "390dddc753cc4d378b489129d06c4b7d", "publicURL": "http://172.16.0.3:8773/services/Cloud"}], "endpoints_links": [], "type": "ec2", "name": "nova_ec2"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da", "region": "RegionOne", "internalURL": "http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da", "id": "9e60268a5aaf422d9e42f0caab0a19b4", "publicURL": "http://172.16.0.3:8004/v1/8c1751e0ce714736a63fee3c776164da"}], "endpoints_links": [], "type": "orchestration", "name": "heat"}, {"endpoints": [{"adminURL": "http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da", "region": "RegionOne", "internalURL": "http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da", "id": "12e78e06595f48339baebdb5d4309c70", "publicURL": "http://172.16.0.3:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da"}], "endpoints_links": [], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://192.168.0.2:35357/v2.0", "region": "RegionOne", "internalURL": "http://192.168.0.2:5000/v2.0", "id": "404cceb349614eb39857742970408301", "publicURL": "http://172.16.0.3:5000/v2.0"}], "endpoints_links": [], "type": "identity", "name": "keystone"}], "user": {"username": "admin", "roles_links": [], "name": "admin", "roles": [{"id": "888bdf92213a477ba9f10554bc382e57", "name": "admin"}], "enabled": true, "email": "admin@localhost", "id": "13baa553aae44adca6615e711fd2f6d9"}, "metadata": {"is_admin": 0, "roles": []}}}'
+ERROR_AUTH_CONTENT = b'{"access": {}}'
+ERROR_TOKEN_CONTENT = b'{"error":{"code":"code","title":"title","message":"message",", URL":"URL"},"access": {}}'
+
+VALID_TOKENS = {
+ PROJECT: {
+ # make sure the expired time of the token is later than now
+ "expires": (datetime.now() + timedelta(1)).strftime("%Y-%m-%dT%H:%M:%SZ")
+ }
+}
+
+EMPTY_TOKENS = {}
+
+REGION_NAME = "RegionOne"
+ERROR_REGION_NAME = "ERROR"
+SERVICE_NAME = "nova"
+ERROR_SERVICE_NAME = "ERROR"
+
+REGION_URL = "http://10.56.20.239:8774/v2/329e0576da594c62a911d0dccb1238a7"
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_availability_zones.py b/app/test/fetch/api_fetch/test_data/api_fetch_availability_zones.py
new file mode 100644
index 0000000..f6e717c
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_availability_zones.py
@@ -0,0 +1,71 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+AVAILABILITY_ZONE_RESPONSE = {
+ "availabilityZoneInfo": [
+ {
+ "hosts": {
+ "node-6.cisco.com": {
+ }
+ },
+ "zoneName": "internal",
+ "zoneState": {
+ "available": True
+ }
+ },
+ {
+ "hosts": {
+ "node-5.cisco.com": {
+ }
+ },
+ "zoneName": "osdna-zone",
+ "zoneState": {
+ "available": True
+ }
+ }
+ ]
+}
+GET_REGION_RESULT = [
+ {
+ "available": True,
+ "hosts": {
+ "node-6.cisco.com": {
+ }
+ },
+ "id": "internal",
+ "master_parent_id": "RegionOne",
+ "master_parent_type": "region",
+ "name": "internal",
+ "parent_id": "RegionOne-availability_zones",
+ "parent_text": "Availability Zones",
+ "parent_type": "availability_zones_folder"
+ },
+ {
+ "available": True,
+ "hosts": {
+ "node-5.cisco.com": {
+ }
+ },
+ "id": "osdna-zone",
+ "master_parent_id": "RegionOne",
+ "master_parent_type": "region",
+ "name": "osdna-zone",
+ "parent_id": "RegionOne-availability_zones",
+ "parent_text": "Availability Zones",
+ "parent_type": "availability_zones_folder"
+ }
+]
+RESPONSE_WITHOUT_AVAILABILITY_ZONE = {"text": "test"}
+WRONG_RESPONSE = {"status": 400}
+EMPTY_AVAILABILITY_ZONE_RESPONSE = {
+ "availabilityZoneInfo": []
+}
+ENDPOINT = "http://10.56.20.239:8774"
+PROJECT = "admin"
+REGION_NAME = "RegionOne"
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_host_instances.py b/app/test/fetch/api_fetch/test_data/api_fetch_host_instances.py
new file mode 100644
index 0000000..d6f8ea6
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_host_instances.py
@@ -0,0 +1,85 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+PROJECT_LIST = [
+ {
+ 'name': 'OSDNA-project',
+ },
+ {
+ 'name': 'admin',
+ }
+]
+
+HOST = {
+ 'host_type': ['Compute'],
+}
+
+NON_COMPUTE_HOST = {
+ 'host_type': [],
+}
+
+HOST_NAME = "node-5.cisco.com"
+
+GET_INSTANCES_FROM_API = [
+ {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "local_name": "instance-00000002",
+ "uuid": "6f29c867-9150-4533-8e19-70d749b172fa"
+ },
+ {
+ "host": "node-5.cisco.com",
+ "id": "79e20dbf-a46d-46ee-870b-e0c9f7b357d9",
+ "local_name": "instance-0000001c",
+ "uuid": "79e20dbf-a46d-46ee-870b-e0c9f7b357d9"
+ },
+ {
+ "host": "node-5.cisco.com",
+ "id": "bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "local_name": "instance-00000026",
+ "uuid": "bf0cb914-b316-486c-a4ce-f22deb453c52"
+ }
+]
+
+GET_SERVERS_RESPONSE = {
+ "hypervisors": [
+ {
+ "hypervisor_hostname": "node-5.cisco.com",
+ "id": 1,
+ "servers": [
+ {
+ "name": "instance-00000002",
+ "uuid": "6f29c867-9150-4533-8e19-70d749b172fa"
+ },
+ {
+ "name": "instance-0000001c",
+ "uuid": "79e20dbf-a46d-46ee-870b-e0c9f7b357d9"
+ },
+ {
+ "name": "instance-00000026",
+ "uuid": "bf0cb914-b316-486c-a4ce-f22deb453c52"
+ }
+ ]
+ }
+ ]
+}
+
+RESPONSE_WITHOUT_HYPERVISORS = {
+ "text": "test"
+}
+
+RESPONSE_WITHOUT_SERVERS = {
+ "hypervisors": [
+ {
+
+ }
+ ]
+}
+
+INSTANCE_FOLDER_ID = "node-5.cisco.com-instances"
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_host_project_hosts.py b/app/test/fetch/api_fetch/test_data/api_fetch_host_project_hosts.py
new file mode 100644
index 0000000..3ef1ac7
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_host_project_hosts.py
@@ -0,0 +1,225 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+HOST_DOC = {
+ "host": "node-6.cisco.com",
+ "host_type": [],
+ "id": "node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ },
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ }
+ },
+ "zone": "internal"
+}
+
+NONEXISTENT_TYPE = "nova"
+COMPUTE_TYPE = "Compute"
+ZONE = "internal"
+HOST_ZONE = "Test"
+
+REGION_NAME = "RegionOne"
+TEST_PROJECT_NAME = "Test"
+PROJECT_NAME = "admin"
+
+AVAILABILITY_ZONE_RESPONSE = {
+ "availabilityZoneInfo": [
+ {
+ "hosts": {
+ "node-6.cisco.com": {
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ },
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ }
+ }
+ },
+ "zoneName": "internal",
+ "zoneState": {
+ "available": True
+ }
+ },
+ {
+ "hosts": {
+ "node-5.cisco.com": {
+ "nova-compute": {
+ "active": True,
+ "available": True,
+ }
+ }
+ },
+ "zoneName": "osdna-zone",
+ "zoneState": {
+ "available": True
+ }
+ }
+ ]
+}
+
+AVAILABILITY_ERROR_RESPONSE = {'status': 400}
+
+HYPERVISORS_RESPONSE = {
+ "hypervisors": []
+}
+
+HYPERVISORS_ERROR_RESPONSE = {'status': 400}
+
+HOST_TO_BE_FETCHED_IP = {
+ "host": "node-5.cisco.com",
+ "id": "node-5.cisco.com"
+}
+
+IP_ADDRESS_RESPONSE = [
+ {
+ "ip_address": "192.168.0.4"
+ }
+]
+
+HOSTS_TO_BE_FETCHED_NETWORK_DETAILS = [
+ {
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller"
+ ],
+ "id": "node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ },
+ {
+ "host": "node-5.cisco.com",
+ "host_type": [
+ "Compute"
+ ],
+ "id": "node-5.cisco.com",
+ "name": "node-5.cisco.com",
+ }
+]
+
+NETWORKS_DETAILS_RESPONSE = [
+ {
+ "configurations": "{}",
+ "host": "node-6.cisco.com"
+ },
+ {
+ "configurations": "{}",
+ "host": "node-6.cisco.com",
+ },
+ {
+ "configurations": "{}",
+ "host": "node-6.cisco.com",
+ }
+]
+
+REGION_URL = "http://192.168.0.2:8776/v2/329e0576da594c62a911d0dccb1238a7"
+AVAILABILITY_ZONE = {
+ "hosts": {
+ "node-6.cisco.com": {
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ },
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ }
+ }
+ },
+ "zoneName": "internal"
+}
+
+HOST_NAME = "node-6.cisco.com"
+
+GET_FOR_REGION_INFO = [
+ {
+ "config": {
+ },
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ },
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ }
+ },
+ "zone": "internal"
+ },
+ {
+ "host": "node-5.cisco.com",
+ "host_type": [
+ "Compute"
+ ],
+ "id": "node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "name": "node-5.cisco.com",
+ "os_id": "1",
+ "parent_id": "osdna-zone",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-compute": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:22:42.000000"
+ }
+ },
+ "zone": "osdna-zone"
+ }
+]
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_networks.py b/app/test/fetch/api_fetch/test_data/api_fetch_networks.py
new file mode 100644
index 0000000..5079a92
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_networks.py
@@ -0,0 +1,72 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+NETWORKS_RESPONSE = {
+ "networks": [
+ {
+ "id": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "subnets": [
+ "cae3c81d-9a27-48c4-b8f6-32867ca03134"
+ ],
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ ]
+}
+
+NETWORKS_RESULT = [
+ {
+ "id": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "subnets": {
+ "test23": {
+ "cidr": "172.16.12.0/24",
+ "id": "cae3c81d-9a27-48c4-b8f6-32867ca03134",
+ "name": "test23",
+ "network_id": "0abe6331-0d74-4bbd-ad89-a5719c3793e4",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ },
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "master_parent_type": "project",
+ "master_parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "parent_type": "networks_folder",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "project": "Calipso-project",
+ "cidrs": ["172.16.12.0/24"],
+ "subnet_ids": ["cae3c81d-9a27-48c4-b8f6-32867ca03134"],
+ "network": "8673c48a-f137-4497-b25d-08b7b218fd17"
+ }
+]
+
+WRONG_NETWORK_RESPONSE = {
+}
+
+SUBNETS_RESPONSE = {
+ "subnets": [
+ {
+ "cidr": "172.16.12.0/24",
+ "id": "cae3c81d-9a27-48c4-b8f6-32867ca03134",
+ "name": "test23",
+ "network_id": "0abe6331-0d74-4bbd-ad89-a5719c3793e4",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ ]
+}
+
+ENDPOINT = "http://10.56.20.239:9696"
+WRONG_SUBNETS_RESPONSE = {}
+
+PROJECT = {
+ "description": "",
+ "enabled": True,
+ "id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "name": "Calipso-project"
+ }
+
+REGION_NAME = "RegionOne"
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_ports.py b/app/test/fetch/api_fetch/test_data/api_fetch_ports.py
new file mode 100644
index 0000000..fc0552c
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_ports.py
@@ -0,0 +1,72 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+PORTS_RESPONSE = {
+ "ports": [
+ {
+ "id": "16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "mac_address": "fa:16:3e:d7:c5:16",
+ "name": "",
+ "network_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ }
+ ]
+}
+
+PORTS_RESULT_WITH_NET = [
+ {
+ "id": "16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "mac_address": "fa:16:3e:d7:c5:16",
+ "name": "fa:16:3e:d7:c5:16",
+ "network_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "master_parent_type": "network",
+ "master_parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "parent_type": "ports_folder",
+ "parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe-ports",
+ "parent_text": "Ports",
+ }
+]
+
+PORTS_RESULT_WITHOUT_NET = [
+ {
+ "id": "16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "mac_address": "fa:16:3e:d7:c5:16",
+ "name": "16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "network_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "master_parent_type": "network",
+ "master_parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "parent_type": "ports_folder",
+ "parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe-ports",
+ "parent_text": "Ports",
+ }
+]
+
+PORTS_RESULT_WITH_PROJECT = [
+ {
+ "id": "16620a58-c48c-4195-b9c1-779a8ba2e6f8",
+ "mac_address": "fa:16:3e:d7:c5:16",
+ "name": "fa:16:3e:d7:c5:16",
+ "network_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "master_parent_type": "network",
+ "master_parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "parent_type": "ports_folder",
+ "parent_id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe-ports",
+ "parent_text": "Ports",
+ "project": "Calipso-project"
+ }
+]
+
+ERROR_PORTS_RESPONSE = {}
+NETWORK = {"id": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe"}
+TENANT = {"id": "75c0eb79ff4a42b0ae4973c8375ddf40", "name": "Calipso-project"}
+ENDPOINT = "http://10.56.20.239:9696"
+REGION_NAME = "RegionOne"
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_projects.py b/app/test/fetch/api_fetch/test_data/api_fetch_projects.py
new file mode 100644
index 0000000..4b2c678
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_projects.py
@@ -0,0 +1,88 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+PROJECTS_CORRECT_RESPONSE = {
+ "projects": [
+ {
+ "name": "Calipso-project"
+ },
+ {
+ "name": "admin",
+ }
+ ]
+}
+
+PROJECT_RESULT = [
+ "Calipso-project",
+ "admin"
+]
+
+PROJECTS_RESPONSE_WITHOUT_PROJECTS = ""
+
+REGION_PROJECTS = [
+ {
+ "description": "",
+ "enabled": True,
+ "id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "name": "OSDNA-project"
+ },
+ {
+ "description": "admin tenant",
+ "enabled": True,
+ "id": "8c1751e0ce714736a63fee3c776164da",
+ "name": "admin"
+ }
+]
+
+USERS_PROJECTS = [
+ "OSDNA-project",
+ "admin"
+]
+
+REGION_URL_NOVER = "http://10.56.20.239:35357"
+
+REGION_RESPONSE = {
+ "tenants": [
+ {
+ "name": "Calipso-project"
+ },
+ {
+ "name": "admin"
+ },
+ {
+ "name": "services"
+ }
+ ]
+}
+
+REGION_RESULT = [
+ {
+ "name": "Calipso-project"
+ },
+ {
+ "name": "admin"
+ }
+]
+
+REGION_RESULT_WITH_NON_USER_PROJECT = [
+ {
+ "name": "Calipso-project"
+ },
+ {
+ "name": "admin"
+ },
+ {
+ "name": "non-user project"
+ }
+]
+
+REGION_ERROR_RESPONSE = []
+
+REGION_NAME = "RegionOne"
+PROJECT_ID = "admin"
diff --git a/app/test/fetch/api_fetch/test_data/api_fetch_regions.py b/app/test/fetch/api_fetch/test_data/api_fetch_regions.py
new file mode 100644
index 0000000..bd7be78
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/api_fetch_regions.py
@@ -0,0 +1,50 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+REGION = "RegionOne"
+ENV = "Mirantis-Liberty"
+
+AUTH_RESPONSE = {
+ "access": {
+ "serviceCatalog": [
+ {
+ "endpoints": [
+ {
+ "adminURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "id": "274cbbd9fd6d4311b78e78dd3a1df51f",
+ "internalURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "region": "RegionOne"
+ }
+ ],
+ "endpoints_links": [],
+ "name": "nova",
+ "type": "compute"
+ }
+ ]
+ }
+}
+
+REGIONS_RESULT = [
+ {
+ "id": "RegionOne",
+ "endpoints": {
+ "nova": {
+ "adminURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "id": "274cbbd9fd6d4311b78e78dd3a1df51f",
+ "internalURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "service_type": "compute"
+ }
+ },
+ "name": "RegionOne",
+ "parent_type": "regions_folder",
+ "parent_id": ENV + "-regions",
+ }
+]
diff --git a/app/test/fetch/api_fetch/test_data/configurations.py b/app/test/fetch/api_fetch/test_data/configurations.py
new file mode 100644
index 0000000..ba15346
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/configurations.py
@@ -0,0 +1,52 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+CONFIGURATIONS = {
+ "configuration": [
+ {
+ "mock": "True",
+ "host": "10.56.20.239",
+ "name": "mysql",
+ "password": "102QreDdiD5sKcvNf9qbHrmr",
+ "port": 3307.0,
+ "user": "root",
+ "schema": "nova"
+ },
+ {
+ "name": "OpenStack",
+ "host": "10.56.20.239",
+ "admin_token": "38MUh19YWcgQQUlk2VEFQ7Ec",
+ "port": "5000",
+ "user": "admin",
+ "pwd": "admin"
+ },
+ {
+ "host": "10.56.20.239",
+ "key": "/Users/xiaocdon/.ssh/id_rsa",
+ "name": "CLI",
+ "pwd": "",
+ "user": "root"
+ },
+ {
+ "name": "AMQP",
+ "host": "10.56.20.239",
+ "port": "5673",
+ "user": "nova",
+ "password": "NF2nSv3SisooxPkCTr8fbfOa"
+ }
+ ],
+ "distribution": "Mirantis-8.0",
+ "last_scanned:": "5/8/16",
+ "name": "Mirantis-Liberty-Xiaocong",
+ "network_plugins": [
+ "OVS"
+ ],
+ "operational": "yes",
+ "type": "environment"
+} \ No newline at end of file
diff --git a/app/test/fetch/api_fetch/test_data/regions.py b/app/test/fetch/api_fetch/test_data/regions.py
new file mode 100644
index 0000000..9945386
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/regions.py
@@ -0,0 +1,110 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+REGIONS = {
+ "RegionOne": {
+ "endpoints": {
+ "ceilometer": {
+ "adminURL": "http://192.168.0.2:8777",
+ "id": "617177a3dcb64560a5a79ab0a91a7225",
+ "internalURL": "http://192.168.0.2:8777",
+ "publicURL": "http://172.16.0.3:8777",
+ "service_type": "metering"
+ },
+ "cinder": {
+ "adminURL": "http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da",
+ "id": "05643f2cf9094265b432376571851841",
+ "internalURL": "http://192.168.0.2:8776/v1/8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8776/v1/8c1751e0ce714736a63fee3c776164da",
+ "service_type": "volume"
+ },
+ "cinderv2": {
+ "adminURL": "http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da",
+ "id": "2c30937688e944889db4a64fab6816e6",
+ "internalURL": "http://192.168.0.2:8776/v2/8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8776/v2/8c1751e0ce714736a63fee3c776164da",
+ "service_type": "volumev2"
+ },
+ "glance": {
+ "adminURL": "http://192.168.0.2:9292",
+ "id": "475c6c77a94e4e63a5a0f0e767f697a8",
+ "internalURL": "http://192.168.0.2:9292",
+ "publicURL": "http://172.16.0.3:9292",
+ "service_type": "image"
+ },
+ "heat": {
+ "adminURL": "http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da",
+ "id": "9e60268a5aaf422d9e42f0caab0a19b4",
+ "internalURL": "http://192.168.0.2:8004/v1/8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8004/v1/8c1751e0ce714736a63fee3c776164da",
+ "service_type": "orchestration"
+ },
+ "heat-cfn": {
+ "adminURL": "http://192.168.0.2:8000/v1",
+ "id": "0f04ec6ed49f4940822161bf677bdfb2",
+ "internalURL": "http://192.168.0.2:8000/v1",
+ "publicURL": "http://172.16.0.3:8000/v1",
+ "service_type": "cloudformation"
+ },
+ "keystone": {
+ "adminURL": "http://192.168.0.2:35357/v2.0",
+ "id": "404cceb349614eb39857742970408301",
+ "internalURL": "http://192.168.0.2:5000/v2.0",
+ "publicURL": "http://172.16.0.3:5000/v2.0",
+ "service_type": "identity"
+ },
+ "neutron": {
+ "adminURL": "http://192.168.0.2:9696",
+ "id": "8dc28584da224c4b9671171ead3c982a",
+ "internalURL": "http://192.168.0.2:9696",
+ "publicURL": "http://172.16.0.3:9696",
+ "service_type": "network"
+ },
+ "nova": {
+ "adminURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "id": "274cbbd9fd6d4311b78e78dd3a1df51f",
+ "internalURL": "http://192.168.0.2:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8774/v2/8c1751e0ce714736a63fee3c776164da",
+ "service_type": "compute"
+ },
+ "nova_ec2": {
+ "adminURL": "http://192.168.0.2:8773/services/Admin",
+ "id": "390dddc753cc4d378b489129d06c4b7d",
+ "internalURL": "http://192.168.0.2:8773/services/Cloud",
+ "publicURL": "http://172.16.0.3:8773/services/Cloud",
+ "service_type": "ec2"
+ },
+ "novav3": {
+ "adminURL": "http://192.168.0.2:8774/v3",
+ "id": "1df917160dfb4ce5b469764fde22b3ab",
+ "internalURL": "http://192.168.0.2:8774/v3",
+ "publicURL": "http://172.16.0.3:8774/v3",
+ "service_type": "computev3"
+ },
+ "swift": {
+ "adminURL": "http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da",
+ "id": "12e78e06595f48339baebdb5d4309c70",
+ "internalURL": "http://192.168.0.2:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da",
+ "publicURL": "http://172.16.0.3:8080/v1/AUTH_8c1751e0ce714736a63fee3c776164da",
+ "service_type": "object-store"
+ },
+ "swift_s3": {
+ "adminURL": "http://192.168.0.2:8080",
+ "id": "4f655c8f2bef46a0a7ba4a20bba53666",
+ "internalURL": "http://192.168.0.2:8080",
+ "publicURL": "http://172.16.0.3:8080",
+ "service_type": "s3"
+ }
+ },
+ "id": "RegionOne",
+ "name": "RegionOne",
+ "parent_id": "Mirantis-Liberty-Xiaocong-regions",
+ "parent_type": "regions_folder"
+ }
+} \ No newline at end of file
diff --git a/app/test/fetch/api_fetch/test_data/token.py b/app/test/fetch/api_fetch/test_data/token.py
new file mode 100644
index 0000000..2abbdd8
--- /dev/null
+++ b/app/test/fetch/api_fetch/test_data/token.py
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+TOKEN = {'tenant': {
+ 'description': 'admin tenant',
+ 'name': 'admin',
+ 'is_domain': False,
+ 'id': '8c1751e0ce714736a63fee3c776164da',
+ 'enabled': True,
+ 'parent_id': None
+ },
+ 'issued_at': '2016-10-19T23:06:29.000000Z',
+ 'expires': '2016-10-20T00:06:28.615780Z',
+ 'id': 'gAAAAABYB_x10x_6AlA2Y5RJZ6HCcCDSXe0f8vfisKnOM_XCDZvwl2qiwzCQIOYX9mCmRyGojZ2JEjIb0vHL0f0hxqSq84g5jbZpN0h0Un_RkTZXSKf0K1uigbr3q__ilhctLvwWNem6XQSGrav1fQrec_DjdvUxSwuoBSSo82kKQ7SvPSdVwrA',
+ 'token_expiry_time': 1476921988,
+ 'audit_ids': ['2Ps0lRlHRIG80FWamMkwWg']
+} \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/__init__.py b/app/test/fetch/cli_fetch/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/cli_fetch/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/cli_fetch/test_cli_access.py b/app/test/fetch/cli_fetch/test_cli_access.py
new file mode 100644
index 0000000..f393538
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_access.py
@@ -0,0 +1,159 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import time
+
+from discover.fetchers.cli.cli_access import CliAccess
+from test.fetch.cli_fetch.test_data.cli_access import *
+from test.fetch.test_fetch import TestFetch
+from unittest.mock import MagicMock, patch
+from utils.ssh_conn import SshConn
+
+
+class TestCliAccess(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.cli_access = CliAccess()
+
+ @patch("utils.ssh_conn.SshConn.exec")
+ def check_run_result(self, is_gateway_host,
+ enable_cache,
+ cached_command_result, exec_result,
+ expected_result, err_msg,
+ ssh_con_exec):
+ # mock cached commands
+ if not is_gateway_host:
+ self.cli_access.cached_commands = {
+ NON_GATEWAY_CACHED_COMMAND: cached_command_result
+ }
+ else:
+ self.cli_access.cached_commands = {
+ GATEWAY_CACHED_COMMAND: cached_command_result
+ }
+ original_is_gateway_host = SshConn.is_gateway_host
+ SshConn.is_gateway_host = MagicMock(return_value=is_gateway_host)
+ ssh_con_exec.return_value = exec_result
+ result = self.cli_access.run(COMMAND, COMPUTE_HOST_ID,
+ on_gateway=False, enable_cache=enable_cache)
+ self.assertEqual(result, expected_result, err_msg)
+
+ # reset the cached commands after testing
+ self.cli_access.cached_commands = {}
+ # reset method
+ SshConn.is_gateway_host = original_is_gateway_host
+
+ def test_run(self):
+ curr_time = time.time()
+ test_cases = [
+ {
+ "is_gateway_host": True,
+ "enable_cache": False,
+ "cached_command_result": None,
+ "exec_result": RUN_RESULT,
+ "expected_result": RUN_RESULT,
+ "err_msg": "Can't get the " +
+ "result of the command"
+ },
+ {
+ "is_gateway_host": True,
+ "enable_cache": True,
+ "cached_command_result": {
+ "timestamp": curr_time,
+ "result": CACHED_COMMAND_RESULT
+ },
+ "exec_result": None,
+ "expected_result": CACHED_COMMAND_RESULT,
+ "err_msg": "Can't get the cached " +
+ "result of the command " +
+ "when the host is a gateway host"
+ },
+ {
+ "is_gateway_host": False,
+ "enable_cache": True,
+ "cached_command_result": {
+ "timestamp": curr_time,
+ "result": CACHED_COMMAND_RESULT
+ },
+ "exec_result": None,
+ "expected_result": CACHED_COMMAND_RESULT,
+ "err_msg": "Can't get the cached " +
+ "result of the command " +
+ "when the host is not a gateway host"
+ },
+ {
+ "is_gateway_host": True,
+ "enable_cache": True,
+ "cached_command_result": {
+ "timestamp": curr_time - self.cli_access.cache_lifetime,
+ "result": CACHED_COMMAND_RESULT
+ },
+ "exec_result": RUN_RESULT,
+ "expected_result": RUN_RESULT,
+ "err_msg": "Can't get the result " +
+ "of the command when the cached result expired " +
+ "and the host is a gateway host"
+ },
+ {
+ "is_gateway_host": False,
+ "enable_cache": True,
+ "cached_command_result": {
+ "timestamp": curr_time - self.cli_access.cache_lifetime,
+ "result": CACHED_COMMAND_RESULT
+ },
+ "exec_result": RUN_RESULT,
+ "expected_result": RUN_RESULT,
+ "err_msg": "Can't get the result " +
+ "of the command when the cached result expired " +
+ "and the host is a not gateway host"
+ }
+ ]
+
+ for test_case in test_cases:
+ self.check_run_result(test_case["is_gateway_host"],
+ test_case["enable_cache"],
+ test_case["cached_command_result"],
+ test_case["exec_result"],
+ test_case["expected_result"],
+ test_case["err_msg"])
+
+ def test_run_fetch_lines(self):
+ original_run = self.cli_access.run
+ self.cli_access.run = MagicMock(return_value=RUN_RESULT)
+
+ result = self.cli_access.run_fetch_lines(COMMAND, COMPUTE_HOST_ID)
+
+ self.assertEqual(result, FETCH_LINES_RESULT,
+ "Can't get correct result of the command line")
+ self.cli_access.run = original_run
+
+ def test_run_fetch_lines_with_empty_command_result(self):
+ original_run = self.cli_access.run
+ self.cli_access.run = MagicMock(return_value="")
+
+ result = self.cli_access.run_fetch_lines(COMMAND, COMPUTE_HOST_ID)
+ self.assertEqual(result, [], "Can't get [] when the command " +
+ "result is empty")
+ self.cli_access.run = original_run
+
+ def test_merge_ws_spillover_lines(self):
+ fixed_lines = self.cli_access.merge_ws_spillover_lines(LINES_FOR_FIX)
+ self.assertEqual(fixed_lines, FIXED_LINES, "Can't merge the " +
+ "ws-separated spillover lines")
+
+ def test_parse_line_with_ws(self):
+ parse_line = self.cli_access.parse_line_with_ws(LINE_FOR_PARSE, HEADERS)
+ self.assertEqual(parse_line, PARSED_LINE, "Can't parse the line with ws")
+
+ def test_parse_cmd_result_with_whitespace(self):
+ result = self.cli_access.parse_cmd_result_with_whitespace(FIXED_LINES,
+ HEADERS,
+ remove_first=False)
+ self.assertEqual(result, PARSED_CMD_RESULT,
+ "Can't parse the cmd result with whitespace")
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_host_pnics.py b/app/test/fetch/cli_fetch/test_cli_fetch_host_pnics.py
new file mode 100644
index 0000000..f5f327e
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_host_pnics.py
@@ -0,0 +1,135 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_host_pnics import CliFetchHostPnics
+from test.fetch.cli_fetch.test_data.cli_fetch_host_pnics import *
+from test.fetch.test_fetch import TestFetch
+from unittest.mock import MagicMock
+from unittest.mock import call
+
+
+class TestCliFetchHostPnics(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchHostPnics()
+ self.fetcher.set_env(self.env)
+
+ def check_get_result(self, host,
+ interface_lines, interface_names,
+ interface_details, expected_result,
+ err_msg):
+ original_get_by_id = self.fetcher.inv.get_by_id
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_find_interface_details = self.fetcher.find_interface_details
+
+ self.fetcher.inv.get_by_id = MagicMock(return_value=host)
+ self.fetcher.run_fetch_lines = MagicMock(return_value=interface_lines)
+ self.fetcher.find_interface_details = MagicMock(side_effect=
+ interface_details)
+ result = self.fetcher.get(PNICS_FOLDER_ID)
+ self.assertEqual(result, expected_result, err_msg)
+
+ if interface_names:
+ interface_calls = [call(HOST_ID, interface_name) for
+ interface_name in interface_names]
+ self.fetcher.find_interface_details.assert_has_calls(interface_calls,
+ any_order=True)
+ # reset the methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.find_interface_details = original_find_interface_details
+
+ def test_get(self):
+ test_cases = [
+ {
+ "host": NETWORK_NODE,
+ "interface_lines": INTERFACE_LINES,
+ "interface_names": INTERFACE_NAMES,
+ "interface_details": [INTERFACE, None],
+ "expected_results": INTERFACES_GET_RESULTS,
+ "err_msg": "Can't get interfaces"
+ },
+ {
+ "host": [],
+ "interface_lines": None,
+ "interface_names": None,
+ "interface_details": None,
+ "expected_results": [],
+ "err_msg": "Can't get [] when the host " +
+ "doesn't exist in the database"
+ },
+ {
+ "host": WRONG_NODE,
+ "interface_lines": None,
+ "interface_names": None,
+ "interface_details": None,
+ "expected_results": [],
+ "err_msg": "Can't get [] when the host doesn't " +
+ "have required host type"
+ },
+ {
+ "host": NETWORK_NODE,
+ "interface_lines": [],
+ "interface_names": None,
+ "interface_details":None,
+ "expected_results": [],
+ "err_msg": "Can't get [] when " +
+ "the interface lines is []"
+ }
+ ]
+ for test_case in test_cases:
+ self.check_get_result(test_case["host"],
+ test_case["interface_lines"],
+ test_case["interface_names"],
+ test_case["interface_details"],
+ test_case["expected_results"],
+ test_case["err_msg"])
+
+ def test_find_interface_details(self):
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_handle_line = self.fetcher.handle_line
+ original_set_interface_data = self.fetcher.set_interface_data
+
+ self.fetcher.run_fetch_lines = MagicMock(return_value=IFCONFIG_CM_RESULT)
+ self.fetcher.handle_line = MagicMock()
+ self.fetcher.set_interface_data = MagicMock()
+
+ result = self.fetcher.find_interface_details(HOST_ID, INTERFACE_NAME)
+
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.handle_line = original_handle_line
+ self.fetcher.set_interface_data = original_set_interface_data
+
+ self.assertEqual(result, INTERFACE_DETAILS, "Can't get interface details")
+
+ def test_handle_mac_address_line(self):
+ self.fetcher.handle_line(RAW_INTERFACE, MAC_ADDRESS_LINE)
+ self.assertEqual(RAW_INTERFACE["mac_address"], MAC_ADDRESS,
+ "Can't get the correct mac address")
+
+ # Test failed, defect, result: addr: expected result: fe80::f816:3eff:fea1:eb73/64
+ def test_handle_ipv6_address_line(self):
+ self.fetcher.handle_line(RAW_INTERFACE, IPV6_ADDRESS_LINE)
+ self.assertEqual(RAW_INTERFACE['IPv6 Address'], IPV6_ADDRESS,
+ "Can' get the correct ipv6 address")
+
+ def test_handle_ipv4_address_line(self):
+ self.fetcher.handle_line(RAW_INTERFACE, IPV4_ADDRESS_LINE)
+ self.assertEqual(RAW_INTERFACE['IP Address'], IPV4_ADDRESS,
+ "Can't get the correct ipv4 address")
+
+ def test_set_interface_data(self):
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ self.fetcher.run_fetch_lines = MagicMock(return_value=ETHTOOL_RESULT)
+ self.fetcher.set_interface_data(INTERFACE_FOR_SET)
+ self.assertEqual(INTERFACE_FOR_SET, INTERFACE_AFTER_SET, "Can't get the attributes of the "
+ "interface from the CMD result")
+
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_host_pnics_vpp.py b/app/test/fetch/cli_fetch/test_cli_fetch_host_pnics_vpp.py
new file mode 100644
index 0000000..805e36d
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_host_pnics_vpp.py
@@ -0,0 +1,34 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_host_pnics_vpp import CliFetchHostPnicsVpp
+from test.fetch.test_fetch import TestFetch
+from unittest.mock import MagicMock
+from test.fetch.cli_fetch.test_data.cli_fetch_host_pnics_vpp import *
+
+
+class TestCliFetchHostPnicsVpp(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchHostPnicsVpp()
+ self.fetcher.set_env(self.env)
+
+ def test_get(self):
+ # store original method
+ original_find_items = self.fetcher.inv.find_items
+
+ # mock the method
+ self.fetcher.inv.find_items = MagicMock(return_value=VEDGES)
+
+ result = self.fetcher.get(ID)
+ # reset the method
+ self.fetcher.inv.find_items = original_find_items
+
+ self.assertNotEqual(result, [], "Can't get the pnics info") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_host_vservices.py b/app/test/fetch/cli_fetch/test_cli_fetch_host_vservices.py
new file mode 100644
index 0000000..c33faca
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_host_vservices.py
@@ -0,0 +1,132 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_host_vservices import CliFetchHostVservices
+from test.fetch.test_fetch import TestFetch
+from test.fetch.cli_fetch.test_data.cli_fetch_host_verservices import *
+from unittest.mock import MagicMock
+
+
+class TestCliFetchHostVservices(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchHostVservices()
+ self.fetcher.set_env(self.env)
+
+ def test_get(self):
+ # store original get_single method
+ original_get_single = self.fetcher.inv.get_single
+ # mock the host data
+ self.fetcher.inv.get_single = MagicMock(return_value=NETWORK_HOST)
+ # store original run_fetch_lines method
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ # mock command line results
+ self.fetcher.run_fetch_lines = MagicMock(return_value=NAMESPACES)
+
+ # only test the logic on get method, mock the set_details method
+ original_set_details = self.fetcher.set_details
+ self.fetcher.set_details = MagicMock()
+
+ result = self.fetcher.get(NETWORK_HOST['id'])
+ # reset methods
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.set_details = original_set_details
+ self.fetcher.inv.get_single = original_get_single
+
+ self.assertNotEqual(result, [], "Can't get verservices")
+
+ def test_get_with_wrong_host_type(self):
+ # store original get_single method
+ original_get_single = self.fetcher.inv.get_single
+ # mock the host data
+ self.fetcher.inv.get_single = MagicMock(return_value=COMPUTE_HOST)
+ result = self.fetcher.get(COMPUTE_HOST['id'])
+
+ self.fetcher.inv.get_single = original_get_single
+
+ self.assertEqual(result, [], "Can't get empty array when the host_type doesn't contain Network")
+
+ def test_set_details(self):
+ # store orginal methods
+ original_get_router_name = self.fetcher.get_router_name
+ original_get_network_name = self.fetcher.get_network_name
+ original_get_type = self.fetcher.agents_list.get_type
+
+ # mock methods
+ self.fetcher.get_network_name = MagicMock(return_value=ROUTER[0]['name'])
+ self.fetcher.get_router_name = MagicMock(return_value=ROUTER[0]['name'])
+ self.fetcher.agents_list.get_type = MagicMock(return_value=AGENT)
+
+ self.fetcher.set_details(NETWORK_HOST['id'], LOCAL_SERVICES_IDS[0])
+
+ # reset methods
+ self.fetcher.get_network_name = original_get_network_name
+ self.fetcher.get_router_name = original_get_router_name
+ self.fetcher.agents_list.get_type = original_get_type
+
+ self.assertIn("name", LOCAL_SERVICES_IDS[0], "Can't add name")
+ self.assertIn("parent_id", LOCAL_SERVICES_IDS[0], "Can't add parent id")
+
+ def test_get_network_name(self):
+ # store original method
+ original_get_objects_list_for_id = self.fetcher.get_objects_list_for_id
+ # mock the result
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=ROUTER)
+
+ name = self.fetcher.get_network_name(ID_CLEAN)
+
+ self.fetcher.get_objects_list_for_id = original_get_objects_list_for_id
+ self.assertEqual(name, ROUTER[0]['name'], "Can't get network name")
+
+ def test_get_network_without_router(self):
+ # store original method
+ original_get_objects_list_for_id = self.fetcher.get_objects_list_for_id
+ # mock the result
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=[])
+
+ name = self.fetcher.get_network_name(ID_CLEAN)
+
+ self.fetcher.get_objects_list_for_id = original_get_objects_list_for_id
+ self.assertEqual(name, ID_CLEAN, "Can't use the id as the name when network info from database is empty")
+
+ def test_get_router_name(self):
+ # store original method
+ original_get_objects_list_for_id = self.fetcher.get_objects_list_for_id
+ # mock the result
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=ROUTER)
+
+ name = self.fetcher.get_router_name(LOCAL_SERVICES_IDS[0], ID_CLEAN)
+
+ self.fetcher.get_objects_list_for_id = original_get_objects_list_for_id
+
+ self.assertIn("name", LOCAL_SERVICES_IDS[0], "Can't get network name")
+ self.assertEqual(name, ROUTER[0]['name'], "Can't get router name")
+
+ def test_set_agent_type(self):
+ # store original get_type method
+ original_get_type = self.fetcher.agents_list.get_type
+ self.fetcher.agents_list.get_type = MagicMock(return_value=AGENT)
+
+ self.fetcher.set_agent_type(VSERVICE)
+ # reset method
+ self.fetcher.set_agent_type = original_get_type
+ self.assertIn("parent_id", VSERVICE, "Can't add parent id to vservice document")
+
+ def test_set_agent_type_without_agent(self):
+ # store original get_type method
+ original_get_type = self.fetcher.agents_list.get_type
+ self.fetcher.agents_list.get_type = MagicMock(return_value={})
+
+ self.fetcher.set_agent_type(VSERVICE)
+ # reset method
+ self.fetcher.set_agent_type = original_get_type
+ self.assertIn("parent_id", VSERVICE, "Can't add parent id to vservice document")
+ self.assertEqual(VSERVICE['parent_type'], "vservice_miscellenaous_folder",
+ "Can't add document to miscellenaous folder when it doesn't have agent") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics.py b/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics.py
new file mode 100644
index 0000000..5a57b9c
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics.py
@@ -0,0 +1,111 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_instance_vnics import CliFetchInstanceVnics
+from test.fetch.test_fetch import TestFetch
+from test.fetch.cli_fetch.test_data.cli_fetch_instance_vnics import *
+from unittest.mock import MagicMock
+
+
+class TestCliFetchInstanceVnics(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchInstanceVnics()
+ self.fetcher.set_env(self.env)
+
+ def test_get(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_get_vnics_from_dumpxml = self.fetcher.get_vnics_from_dumpxml
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(side_effect=[INSATNCE, COMPUTE_HOST])
+ self.fetcher.run_fetch_lines = MagicMock(return_value=INSTANCES_LIST)
+ self.fetcher.get_vnics_from_dumpxml = MagicMock(return_value=VNICS_FROM_DUMP_XML)
+
+ result = self.fetcher.get(VNICS_FOLDER['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.get_vnics_from_dumpxml = original_get_vnics_from_dumpxml
+
+ self.assertNotEqual(result, [], "Can't get vnics with VNICS folder id")
+
+ def test_get_without_instance(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=[])
+
+ result = self.fetcher.get(VNICS_FOLDER['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ self.assertEqual(result, [], "Can't get empty array when the instance can't be found")
+
+ def test_get_without_host(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(side_effect=[[], NETWORK_HOST])
+
+ result = self.fetcher.get(VNICS_FOLDER['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ self.assertEqual(result, [], "Can't get empty array when the host doesn't contain network host type")
+
+ def test_get_vnics_from_dumpxml(self):
+ # store original functions
+ original_run = self.fetcher.run
+ original_set_vnic_properties = self.fetcher.set_vnic_properties
+
+ # mock the functions
+ self.fetcher.run = MagicMock(return_value=DUMPXML)
+ self.fetcher.set_vnic_properties = MagicMock()
+
+ vnics = self.fetcher.get_vnics_from_dumpxml(ID, INSATNCE)
+ # reset functions
+ self.fetcher.run = original_run
+ self.fetcher.set_vnic_properties = original_set_vnic_properties
+
+ self.assertNotEqual(vnics, [], "Can't get vnics")
+
+ def test_get_vnics_from_dumpxml_with_empty_command_result(self):
+ # store original functions
+ original_run = self.fetcher.run
+
+ # mock the functions
+ self.fetcher.run = MagicMock(return_value=" ")
+
+ vnics = self.fetcher.get_vnics_from_dumpxml(ID, INSATNCE)
+ # reset functions
+ self.fetcher.run = original_run
+
+ self.assertEqual(vnics, [], "Can't get empty array when the dumpxml is empty")
+
+ def test_get_vnics_from_dumpxml_with_wrong_instance(self):
+ # store original functions
+ original_run = self.fetcher.run
+
+ # mock the functions
+ self.fetcher.run = MagicMock(return_value=WRONG_DUMPXML)
+
+ vnics = self.fetcher.get_vnics_from_dumpxml(ID, INSATNCE)
+ # reset functions
+ self.fetcher.run = original_run
+
+ self.assertEqual(vnics, [], "Can't get empty array when the instance is wrong") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_ovs.py b/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_ovs.py
new file mode 100644
index 0000000..24a1b5d
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_ovs.py
@@ -0,0 +1,36 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.cli_fetch_instance_vnics_ovs import CliFetchInstanceVnicsOvs
+from test.fetch.test_fetch import TestFetch
+from test.fetch.cli_fetch.test_data.cli_fetch_instance_vnics import *
+from unittest.mock import MagicMock
+
+
+class TestCliFetchInstanceVnicsOvs(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchInstanceVnicsOvs()
+ self.fetcher.set_env(self.env)
+
+ def test_set_vnic_properties(self):
+ # store original method
+ original_set = self.fetcher.inv.set
+ self.fetcher.inv.set = MagicMock()
+
+ self.fetcher.set_vnic_properties(VNIC, INSATNCE)
+ # reset method
+ self.fetcher.inv.set = original_set
+
+ self.assertIn("source_bridge", VNIC, "Can't set source_bridge for ovs vnic")
+
+ def test_get_vnic_name(self):
+ name = self.fetcher.get_vnic_name(VNIC, INSATNCE)
+ self.assertNotEqual(name, None, "Can't get vnic name") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_vpp.py b/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_vpp.py
new file mode 100644
index 0000000..46c25fb
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_instance_vnics_vpp.py
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.cli_fetch_instance_vnics_vpp import CliFetchInstanceVnicsVpp
+from test.fetch.cli_fetch.test_data.cli_fetch_instance_vnics import *
+from test.fetch.test_fetch import TestFetch
+
+
+class TestCliFetchInstanceVnicsVpp(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchInstanceVnicsVpp()
+
+ def test_get_name(self):
+ name = self.fetcher.get_vnic_name(VNIC, INSATNCE)
+ self.assertNotEqual(name, None, "Can't get vnic name") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors.py b/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors.py
new file mode 100644
index 0000000..23e0a99
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors.py
@@ -0,0 +1,66 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_vconnectors import CliFetchVconnectors
+from test.fetch.test_fetch import TestFetch
+from test.fetch.cli_fetch.test_data.cli_fetch_vconnectors import *
+from unittest.mock import MagicMock
+
+
+class TestCliFetchVconnectors(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchVconnectors()
+ self.fetcher.set_env(self.env)
+
+ def test_get(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+ original_get_vconnectors = self.fetcher.get_vconnectors
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=HOST)
+ self.fetcher.get_vconnectors = MagicMock(return_value=VCONNECTORS)
+
+ result = self.fetcher.get(VCONNECTORS_FOLDER['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+ self.fetcher.get_vconnectors = original_get_vconnectors
+
+ self.assertEqual(result, VCONNECTORS, "Can't get the vconnectors")
+
+ def test_get_without_host(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=[])
+
+ result = self.fetcher.get(VCONNECTORS_FOLDER['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ self.assertEqual(result, [], "Can't get empty array when the host doesn't exist")
+
+ def test_get_with_wrong_host(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=WRONG_HOST)
+
+ result = self.fetcher.get(VCONNECTORS_FOLDER['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ self.assertEqual(result, [], "Can't get empty array when the host doesn't contain host type") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_ovs.py b/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_ovs.py
new file mode 100644
index 0000000..cc882a1
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_ovs.py
@@ -0,0 +1,38 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_vconnectors_ovs import CliFetchVconnectorsOvs
+from test.fetch.test_fetch import TestFetch
+from test.fetch.cli_fetch.test_data.cli_fetch_vconnectors_ovs import *
+from unittest.mock import MagicMock
+
+
+class TestCliFetchVconnectorsOvs(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchVconnectorsOvs()
+ self.fetcher.set_env(self.env)
+
+ def test_get_vconnectors(self):
+ # store the original methods
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_find_items = self.fetcher.inv.find_items
+
+ # mock the methods
+ self.fetcher.run_fetch_lines = MagicMock(return_value=BRIDGE_RESULT)
+ self.fetcher.inv.find_items = MagicMock(return_value=[])
+
+ result = self.fetcher.get_vconnectors(NETWORK_NODE)
+
+ # reset methods
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.inv.find_items = original_find_items
+
+ self.assertNotEqual(result, [], "Can't get vconnectors with the host id")
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_vpp.py b/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_vpp.py
new file mode 100644
index 0000000..f729c2c
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_vconnectors_vpp.py
@@ -0,0 +1,50 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_vconnectors_vpp import CliFetchVconnectorsVpp
+from test.fetch.test_fetch import TestFetch
+from unittest.mock import MagicMock
+from test.fetch.cli_fetch.test_data.cli_fetch_vconnectors_vpp import *
+
+
+class TestCliFetchVconnectorsVpp(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchVconnectorsVpp()
+ self.fetcher.set_env(self.env)
+
+ def test_get_vconnectors(self):
+ # store original method
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_get_interface_details = self.fetcher.get_interface_details
+
+ # mock methods
+ self.fetcher.run_fetch_lines = MagicMock(return_value=MODE_RESULT)
+ self.fetcher.get_interface_details = MagicMock(return_value=None)
+
+ result = self.fetcher.get_vconnectors(HOST)
+
+ # reset methods
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.get_interface_details = original_get_interface_details
+
+ self.assertNotEqual(result, {}, "Can't get vconnectors info")
+
+ def test_set_interface_details(self):
+ # store original methods
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+
+ # mock method
+ self.fetcher.run_fetch_lines = MagicMock(return_value=INTERFACE_LINES)
+
+ result = self.fetcher.get_interface_details(HOST, INTERFACE_NAME)
+ # restore method
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.assertNotEqual(result, None, "Can't get the interface details") \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_cli_fetch_vservice_vnics.py b/app/test/fetch/cli_fetch/test_cli_fetch_vservice_vnics.py
new file mode 100644
index 0000000..b77f41e
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_cli_fetch_vservice_vnics.py
@@ -0,0 +1,124 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.cli.cli_fetch_vservice_vnics import CliFetchVserviceVnics
+from test.fetch.test_fetch import TestFetch
+from test.fetch.cli_fetch.test_data.cli_fetch_vservice_vnics import *
+from unittest.mock import MagicMock
+
+
+class TestCliFetchVserviceVnics(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = CliFetchVserviceVnics()
+ self.fetcher.set_env(self.env)
+
+ def test_get(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_handle_service = self.fetcher.handle_service
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=NETWORK_NODE)
+ self.fetcher.run_fetch_lines = MagicMock(return_value=NAME_SPACES)
+ self.fetcher.handle_service = MagicMock(return_value=SERVICES)
+
+ result = self.fetcher.get(NETWORK_NODE['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.handle_service = original_handle_service
+
+ self.assertNotEqual(result, [], "Can't get vnics")
+
+ def test_get_with_error_host(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=ERROR_NODE)
+
+ result = self.fetcher.get(NETWORK_NODE['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ self.assertEqual(result, [], "Can't get empty array when the host doesn't contain host_type")
+
+ def test_get_with_compute_host(self):
+ # store original methods
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ # mock methods
+ self.fetcher.inv.get_by_id = MagicMock(return_value=COMPUTE_NODE)
+
+ result = self.fetcher.get(NETWORK_NODE['id'])
+
+ # reset methods
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ self.assertEqual(result, [], "Can't get empty array when the host type doesn't contain network")
+
+ def test_handle_service(self):
+ # store original method
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_set_interface_data = self.fetcher.set_interface_data
+ # mock the method
+ self.fetcher.run_fetch_lines = MagicMock(return_value=IFCONFIG_RESULT)
+ self.fetcher.set_interface_data = MagicMock()
+ result = self.fetcher.handle_service(NETWORK_NODE['id'], SERVICE_ID)
+ # reset method
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.set_interface_data = original_set_interface_data
+
+ self.assertNotEqual(result, [], "Can't get interfaces data")
+
+ def test_set_interface_data(self):
+ # store original methods
+ original_get_by_field = self.fetcher.inv.get_by_field
+ original_get_by_id = self.fetcher.inv.get_by_id
+ original_set = self.fetcher.inv.set
+
+ # mock the methods
+ self.fetcher.inv.get_by_field = MagicMock(return_value=NETWORK)
+ self.fetcher.inv.get_by_id = MagicMock(return_value=VSERVICE)
+ self.fetcher.inv.set = MagicMock()
+
+ self.fetcher.set_interface_data(VNIC)
+
+ # reset methods
+ self.fetcher.inv.get_by_field = original_get_by_field
+ self.fetcher.inv.get_by_id = original_get_by_id
+ self.fetcher.inv.set = original_set
+
+ self.assertIn("data", VNIC, "Can't set data")
+ self.assertIn("cidr", VNIC, "Can't set cidr")
+ self.assertIn("network", VNIC, "Can't set network")
+
+ def test_handle_mac_address_line(self):
+ self.fetcher.handle_line(RAW_VNIC, MAC_ADDRESS_LINE)
+ self.assertEqual(RAW_VNIC['mac_address'], MAC_ADDRESS, "Can't get the correct mac address from the line")
+
+ def test_handle_ipv4_address_line(self):
+ self.fetcher.handle_line(RAW_VNIC, IPV4_ADDRESS_LINE)
+ self.assertEqual(RAW_VNIC['IP Address'], IPV4_ADDRESS, "Can't get the correct ipv4 address from the line")
+
+ def test_handle_ipv6_address_line(self):
+ self.fetcher.handle_line(RAW_VNIC, IPV6_ADDRESS_LINE)
+ self.assertEqual(RAW_VNIC['IPv6 Address'], IPV6_ADDRESS, "Can't get the correct ipv6 address from the line")
+
+ def test_get_net_size(self):
+ size = self.fetcher.get_net_size(NET_MASK_ARRAY)
+ self.assertEqual(size, SIZE, "Can't get the size of network by netmask")
+
+ def test_get_cidr_for_vnic(self):
+ cidr = self.fetcher.get_cidr_for_vnic(VNIC)
+ self.assertEqual(cidr, CIDR, "the cidr info is wrong")
diff --git a/app/test/fetch/cli_fetch/test_data/__init__.py b/app/test/fetch/cli_fetch/test_data/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/cli_fetch/test_data/cli_access.py b/app/test/fetch/cli_fetch/test_data/cli_access.py
new file mode 100644
index 0000000..b151dc6
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_access.py
@@ -0,0 +1,58 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+COMPUTE_HOST_ID = "node-5.cisco.com"
+COMMAND = "virsh list"
+NON_GATEWAY_CACHED_COMMAND = COMPUTE_HOST_ID + "," + "ssh -o StrictHostKeyChecking=no " + \
+ COMPUTE_HOST_ID + " sudo " + COMMAND
+GATEWAY_CACHED_COMMAND = COMPUTE_HOST_ID + "," + "sudo " + COMMAND
+CACHED_COMMAND_RESULT = " Id Name State\n---\n 2 instance-00000003 running"
+RUN_RESULT = " Id Name State\n---\n 2 instance-00000002 running"
+FETCH_LINES_RESULT = [
+ " Id Name State",
+ "---",
+ " 2 instance-00000002 running"
+]
+
+LINES_FOR_FIX = [
+ "br-ex\t\t8000.005056acc9a2\tno\t\teno33554952",
+ "\t\t\t\t\t\t\tp_ff798dba-0",
+ "\t\t\t\t\t\t\tv_public",
+ "\t\t\t\t\t\t\tv_vrouter_pub",
+ "br-fw-admin\t\t8000.005056ace897\tno\t\teno16777728"
+]
+
+FIXED_LINES = [
+ "br-ex\t\t8000.005056acc9a2\tno\t\teno33554952,p_ff798dba-0,v_public,v_vrouter_pub",
+ "br-fw-admin\t\t8000.005056ace897\tno\t\teno16777728"
+]
+
+PARSED_CMD_RESULT = [
+ {
+ "bridge_id": "8000.005056acc9a2",
+ "bridge_name": "br-ex",
+ "interfaces": "eno33554952,p_ff798dba-0,v_public,v_vrouter_pub",
+ "stp_enabled": "no"
+ },
+ {
+ "bridge_id": "8000.005056ace897",
+ "bridge_name": "br-fw-admin",
+ "interfaces": "eno16777728",
+ "stp_enabled": "no"
+ }
+]
+
+LINE_FOR_PARSE = "br-ex\t\t8000.005056acc9a2\tno\t\teno33554952,p_ff798dba-0,v_public,v_vrouter_pub"
+PARSED_LINE = {
+ "bridge_id": "8000.005056acc9a2",
+ "bridge_name": "br-ex",
+ "interfaces": "eno33554952,p_ff798dba-0,v_public,v_vrouter_pub",
+ "stp_enabled": "no"
+}
+HEADERS = ["bridge_name", "bridge_id", "stp_enabled", "interfaces"]
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics.py
new file mode 100644
index 0000000..316c68a
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics.py
@@ -0,0 +1,147 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+PNICS_FOLDER_ID = "node-6.cisco.com-pnics"
+HOST_ID = "node-6.cisco.com"
+
+NETWORK_NODE = {
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com"
+}
+
+WRONG_NODE = {
+ "host_type": [
+ "Controller"
+ ]
+}
+
+INTERFACE_LINES = [
+ "lrwxrwxrwx 1 root 0 Jul 5 17:17 eno16777728 -> ../../devices/0000:02:00.0/net/eno16777728",
+ "lrwxrwxrwx 1 root 0 Jul 5 17:17 eno33554952 -> ../../devices/0000:02:01.0/net/eno33554952"
+]
+
+INTERFACE_NAMES = ["eno16777728", "eno33554952"]
+
+INTERFACE_NAME = INTERFACE_NAMES[0]
+IFCONFIG_CM_RESULT = [
+ "eno16777728 Link encap:Ethernet HWaddr 00:50:56:ac:e8:97 ",
+ " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1",
+ " RX packets:409056348 errors:0 dropped:0 overruns:0 frame:0",
+ " TX packets:293898173 errors:0 dropped:0 overruns:0 carrier:0",
+ " collisions:0 txqueuelen:1000 ",
+ " RX bytes:103719003730 (103.7 GB) TX bytes:165090993470 (165.0 GB)",
+ ""
+]
+
+INTERFACE_DETAILS = {
+ "host": "node-6.cisco.com",
+ "id": "eno16777728-unknown_mac",
+ "lines": [],
+ "local_name": "eno16777728",
+ "name": "eno16777728",
+ "state": "UP"
+}
+
+MAC_ADDRESS_LINE = "eno16777728 Link encap:Ethernet HWaddr 00:50:56:ac:e8:97 "
+MAC_ADDRESS = "00:50:56:ac:e8:97"
+RAW_INTERFACE = {
+ "host": "node-6.cisco.com",
+ "lines": [],
+ "local_name": "eno16777728",
+ "name": "eno16777728"
+}
+
+INTERFACE_AFTER_LINE_HANDLE = {
+ "host": "node-6.cisco.com",
+ "lines": [MAC_ADDRESS_LINE.strip()],
+ "local_name": "eno16777728",
+ "name": "eno16777728",
+ "id": "eno16777728-" + MAC_ADDRESS,
+ "mac_address": MAC_ADDRESS
+}
+
+INTERFACE_FOR_SET = {
+ "host": "node-6.cisco.com",
+ "lines": [
+ "Link encap:Ethernet HWaddr 00:50:56:ac:e8:97",
+ "UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1"
+ ],
+ "local_name": "eno16777728",
+ "mac_address": "00:50:56:ac:e8:97"
+}
+
+INTERFACE_AFTER_SET = {
+ "host": "node-6.cisco.com",
+ "data": "Link encap:Ethernet HWaddr 00:50:56:ac:e8:97" +
+ "\nUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1",
+ "local_name": "eno16777728",
+ "mac_address": "00:50:56:ac:e8:97",
+ "Supported ports": "[ TP ]",
+ "Supported link modes": ["10baseT/Half 10baseT/Full",
+ "100baseT/Half 100baseT/Full",
+ "1000baseT/Full"],
+ "Supported pause frame use": "No"
+}
+
+INTERFACE = {
+ "Advertised auto-negotiation": "Yes",
+ "Advertised link modes": [
+ "10baseT/Half 10baseT/Full",
+ "100baseT/Half 100baseT/Full",
+ "1000baseT/Full"
+ ],
+ "Advertised pause frame use": "No",
+ "Auto-negotiation": "on",
+ "Current message level": [
+ "0x00000007 (7)",
+ "drv probe link"
+ ],
+ "Duplex": "Full",
+ "Link detected": "yes",
+ "MDI-X": "off (auto)",
+ "PHYAD": "0",
+ "Port": "Twisted Pair",
+ "Speed": "1000Mb/s",
+ "Supported link modes": [
+ "10baseT/Half 10baseT/Full",
+ "100baseT/Half 100baseT/Full",
+ "1000baseT/Full"
+ ],
+ "Supported pause frame use": "No",
+ "Supported ports": "[ TP ]",
+ "Supports Wake-on": "d",
+ "Supports auto-negotiation": "Yes",
+ "Transceiver": "internal",
+ "Wake-on": "d",
+ "data": "Link encap:Ethernet HWaddr 00:50:56:ac:e8:97\nUP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1\nRX packets:408989052 errors:0 dropped:0 overruns:0 frame:0\nTX packets:293849880 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:1000\nRX bytes:103702814216 (103.7 GB) TX bytes:165063440009 (165.0 GB)\n",
+ "host": "node-6.cisco.com",
+ "id": "eno16777728-00:50:56:ac:e8:97",
+ "local_name": "eno16777728",
+ "mac_address": "00:50:56:ac:e8:97",
+ "name": "eno16777728"
+}
+
+INTERFACES_GET_RESULTS = [INTERFACE]
+
+IPV6_ADDRESS_LINE = " inet6 addr: fe80::f816:3eff:fea1:eb73/64 Scope:Link"
+IPV6_ADDRESS = "fe80::f816:3eff:fea1:eb73/64"
+IPV4_ADDRESS_LINE = " inet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0"
+IPV4_ADDRESS = "172.16.13.2"
+
+ETHTOOL_RESULT = [
+ "Settings for eno16777728:",
+ "\tSupported ports: [ TP ]",
+ "\tSupported link modes: 10baseT/Half 10baseT/Full ",
+ "\t 100baseT/Half 100baseT/Full ",
+ "\t 1000baseT/Full ",
+ "\tSupported pause frame use: No",
+]
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics_vpp.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics_vpp.py
new file mode 100644
index 0000000..99bd4cd
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_host_pnics_vpp.py
@@ -0,0 +1,204 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+ID = "node-4.cisco.com-VPP-folders"
+VEDGES = [
+ {
+ "agent_type": "Open vSwitch agent",
+ "binary": "neutron-openvswitch-agent",
+ "configurations" : {
+ "tunneling_ip": "192.168.2.3",
+ "arp_responder_enabled" : True,
+ "extensions" : [
+
+ ],
+ "l2_population" : True,
+ "enable_distributed_routing" : False,
+ "bridge_mappings" : {
+ "physnet1": "br-floating"
+ },
+ "log_agent_heartbeats" : False,
+ "tunnel_types" : [
+ "vxlan"
+ ],
+ "in_distributed_mode" : False
+ },
+ "description" : None,
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-6.cisco.com",
+ "id": "1764430c-c09e-4717-86fa-c04350b1fcbb",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com/node-6.cisco.com-vedges/1764430c-c09e-4717-86fa-c04350b1fcbb",
+ "name": "node-6.cisco.com-OVS",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com/vEdges/node-6.cisco.com-OVS",
+ "object_name": "node-6.cisco.com-OVS",
+ "parent_id": "node-6.cisco.com-vedges",
+ "parent_type": "vedges_folder",
+ "ports" : {
+ "TenGigabitEthernet-g-63489f34-af" : {
+ "id": "8",
+ "name": "qg-63489f34-af",
+ "internal" : True,
+ "tag": "2",
+ "host": "node-4.cisco.com",
+ "state": "up"
+ },
+ "qr-3ff411a2-54" : {
+ "id": "7",
+ "name": "qr-3ff411a2-54",
+ "internal" : True,
+ "tag": "5"
+ },
+ "tap31c19fbe-5d" : {
+ "id": "19",
+ "name": "tap31c19fbe-5d",
+ "internal" : True,
+ "tag": "117"
+ },
+ "br-int" : {
+ "id": "3",
+ "name": "br-int",
+ "internal" : True
+ },
+ "qr-18f029db-77" : {
+ "id": "17",
+ "name": "qr-18f029db-77",
+ "internal" : True,
+ "tag": "105"
+ },
+ "br-tun" : {
+ "id": "13",
+ "name": "br-tun",
+ "internal" : True
+ },
+ "tap82d4992f-4d" : {
+ "id": "9",
+ "name": "tap82d4992f-4d",
+ "internal" : True,
+ "tag": "5"
+ },
+ "tap16620a58-c4" : {
+ "id": "16",
+ "name": "tap16620a58-c4",
+ "internal" : True,
+ "tag": "6"
+ },
+ "p_ff798dba-0" : {
+ "id": "15",
+ "name": "p_ff798dba-0",
+ "internal" : True
+ },
+ "tapee8e5dbb-03" : {
+ "id": "6",
+ "name": "tapee8e5dbb-03",
+ "internal" : True,
+ "tag": "1"
+ },
+ "tap702e9683-0c" : {
+ "id": "20",
+ "name": "tap702e9683-0c",
+ "internal" : True,
+ "tag": "118"
+ },
+ "tapaf69959f-ef" : {
+ "id": "18",
+ "name": "tapaf69959f-ef",
+ "internal" : True,
+ "tag": "105"
+ },
+ "tap5f22f397-d8" : {
+ "id": "11",
+ "name": "tap5f22f397-d8",
+ "internal" : True,
+ "tag": "3"
+ },
+ "qr-bb9b8340-72" : {
+ "id": "1",
+ "name": "qr-bb9b8340-72",
+ "internal" : True,
+ "tag": "3"
+ },
+ "qr-8733cc5d-b3" : {
+ "id": "2",
+ "name": "qr-8733cc5d-b3",
+ "internal" : True,
+ "tag": "4"
+ },
+ "ovs-system" : {
+ "id": "0",
+ "name": "ovs-system",
+ "internal" : True
+ },
+ "br-floating" : {
+ "id": "14",
+ "name": "br-floating",
+ "internal" : True
+ },
+ "qg-57e65d34-3d" : {
+ "id": "10",
+ "name": "qg-57e65d34-3d",
+ "internal" : True,
+ "tag": "2"
+ },
+ "qr-f7b44150-99" : {
+ "id": "4",
+ "name": "qr-f7b44150-99",
+ "internal" : True,
+ "tag": "1"
+ },
+ "tapbf16c3ab-56" : {
+ "id": "5",
+ "name": "tapbf16c3ab-56",
+ "internal" : True,
+ "tag": "4"
+ }
+ },
+ "show_in_tree" : True,
+ "topic": "N/A",
+ "tunnel_ports" : {
+ "br-tun" : {
+ "name": "br-tun",
+ "interface": "br-tun",
+ "type": "internal"
+ },
+ "vxlan-c0a80201" : {
+ "name": "vxlan-c0a80201",
+ "options" : {
+ "local_ip": "192.168.2.3",
+ "out_key": "flow",
+ "in_key": "flow",
+ "df_default": "True",
+ "remote_ip": "192.168.2.1"
+ },
+ "interface": "vxlan-c0a80201",
+ "type": "vxlan"
+ },
+ "vxlan-c0a80202" : {
+ "name": "vxlan-c0a80202",
+ "options" : {
+ "local_ip": "192.168.2.3",
+ "out_key": "flow",
+ "in_key": "flow",
+ "df_default": "True",
+ "remote_ip": "192.168.2.2"
+ },
+ "interface": "vxlan-c0a80202",
+ "type": "vxlan"
+ },
+ "patch-int" : {
+ "name": "patch-int",
+ "options" : {
+ "peer": "patch-tun"
+ },
+ "interface": "patch-int",
+ "type": "patch"
+ }
+ },
+ "type": "vedge"
+}
+ ] \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_host_verservices.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_host_verservices.py
new file mode 100644
index 0000000..94ee38c
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_host_verservices.py
@@ -0,0 +1,276 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+NETWORK_HOST = {
+ "config": {
+ "interfaces": 4,
+ "log_agent_heartbeats": False,
+ "gateway_external_network_id": "",
+ "router_id": "",
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "ex_gw_ports": 2,
+ "routers": 2,
+ "handle_internal_only_routers": True,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "use_namespaces": True,
+ "agent_mode": "legacy"
+ },
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com",
+ "object_name": "node-6.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:10.000000"
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:54.000000"
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:45.000000"
+ },
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:56.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type" : "host",
+ "zone" : "internal"
+}
+
+COMPUTE_HOST = {
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-5.cisco.com",
+ "host_type": [
+ "Compute"
+ ],
+ "id": "node-5.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/osdna-zone/node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "name": "node-5.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/osdna-zone/node-5.cisco.com",
+ "object_name": "node-5.cisco.com",
+ "os_id": "1",
+ "parent_id": "osdna-zone",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-compute": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:42.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "osdna-zone"
+}
+
+NAMESPACES = [
+ 'qdhcp-413de095-01ed-49dc-aa50-4479f43d390e',
+ 'qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc',
+ 'qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe',
+ 'qdhcp-eb276a62-15a9-4616-a192-11466fdd147f',
+ 'qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627',
+ 'qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f',
+ 'qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc',
+ 'qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9',
+ 'qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6',
+ 'haproxy',
+ 'vrouter'
+]
+
+LOCAL_SERVICES_IDS = [
+ {
+ "local_service_id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e"
+ },
+ {
+ "local_service_id": "qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc"
+ },
+ {
+ "local_service_id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe"
+ },
+ {
+ "local_service_id": "qdhcp-eb276a62-15a9-4616-a192-11466fdd147f"
+ },
+ {
+ "local_service_id": "qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627"
+ },
+ {
+ "local_service_id": "qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f"
+ },
+ {
+ "local_service_id": "qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc"
+ },
+ {
+ "local_service_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9"
+ },
+ {
+ "local_service_id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6"
+ }
+]
+
+VSERVICE = {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "local_service_id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "name": "dhcp-osdna-met4",
+ "service_type": "dhcp"
+ }
+
+AGENT = {
+ "description": "DHCP agent",
+ "folder_text": "DHCP servers",
+ "type": "dhcp"
+}
+
+ROUTER = [
+ {"name": "123456"}
+]
+
+ID_CLEAN = "413de095-01ed-49dc-aa50-4479f43d390e"
+# functional test
+INPUT = "node-6.cisco.com"
+OUTPUT = [
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "local_service_id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-aiya",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc",
+ "local_service_id": "qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-123456",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "local_service_id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-osdna-met4",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-eb276a62-15a9-4616-a192-11466fdd147f",
+ "local_service_id": "qdhcp-eb276a62-15a9-4616-a192-11466fdd147f",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-osdna-net3",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627",
+ "local_service_id": "qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-osdna-net1",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "local_service_id": "qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-osdna-net2",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc",
+ "local_service_id": "qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-admin_internal_net",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ },
+ {
+ "admin_state_up": 1,
+ "enable_snat": 1,
+ "gw_port_id": "63489f34-af99-44f4-81de-9a2eb1c1941f",
+ "host": "node-6.cisco.com",
+ "id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "local_service_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "router-osdna-router",
+ "parent_id": "node-6.cisco.com-vservices-routers",
+ "parent_text": "Gateways",
+ "parent_type": "vservice_routers_folder",
+ "service_type": "router",
+ "status": "ACTIVE",
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40"
+ },
+ {
+ "admin_state_up": 1,
+ "enable_snat": 1,
+ "gw_port_id": "57e65d34-3d87-4751-8e95-fc78847a3070",
+ "host": "node-6.cisco.com",
+ "id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6",
+ "local_service_id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "router-router04",
+ "parent_id": "node-6.cisco.com-vservices-routers",
+ "parent_text": "Gateways",
+ "parent_type": "vservice_routers_folder",
+ "service_type": "router",
+ "status": "ACTIVE",
+ "tenant_id": "8c1751e0ce714736a63fee3c776164da"
+ }
+] \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_instance_vnics.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_instance_vnics.py
new file mode 100644
index 0000000..a43b5c2
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_instance_vnics.py
@@ -0,0 +1,288 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+VNICS_FOLDER = {
+ "create_object": True,
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "id": "bf0cb914-b316-486c-a4ce-f22deb453c52-vnics",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/osdna-zone/node-5.cisco.com/node-5.cisco.com-instances/bf0cb914-b316-486c-a4ce-f22deb453c52/bf0cb914-b316-486c-a4ce-f22deb453c52-vnics",
+ "name": "vNICs",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/osdna-zone/node-5.cisco.com/Instances/test/vNICs",
+ "object_name": "vNICs",
+ "parent_id": "bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "parent_type": "instance",
+ "show_in_tree": True,
+ "text": "vNICs",
+ "type": "vnics_folder"
+}
+
+INSATNCE = {
+ "_id": "5806817e4a0a8a3fbe3bee8b",
+ "children_url": "/osdna_dev/discover.py?type=tree&id=bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-5.cisco.com",
+ "id": "bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/osdna-zone/node-5.cisco.com/node-5.cisco.com-instances/bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "ip_address": "192.168.0.4",
+ "local_name": "instance-00000026",
+ "mac_address": "fa:16:3e:e8:7f:04",
+ "name": "test",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/osdna-zone/node-5.cisco.com/Instances/test",
+ "network": [
+ "2e3b85f4-756c-49d9-b34c-f3db13212dbc"
+ ],
+ "network_info": [
+ {
+ "devname": "tap1f72bd15-8a",
+ "id": "1f72bd15-8ab2-43cb-94d7-e823dd845255",
+ "profile": {
+
+ },
+ "vnic_type": "normal",
+ "type": "ovs",
+ "address": "fa:16:3e:e8:7f:04",
+ "qbg_params": None,
+ "network": {
+ "bridge": "br-int",
+ "label": "123456",
+ "subnets": [
+ {
+ "cidr": "172.16.13.0/24",
+ "version": 4,
+ "gateway": {
+ "version": 4,
+ "meta": {
+
+ },
+ "address": "172.16.13.1",
+ "type": "gateway"
+ },
+ "routes": [
+
+ ],
+ "dns": [
+
+ ],
+ "ips": [
+ {
+ "meta": {
+
+ },
+ "version": 4,
+ "type": "fixed",
+ "address": "172.16.13.4",
+ "floating_ips": [
+
+ ]
+ }
+ ],
+ "meta": {
+ "dhcp_server": "172.16.13.2"
+ }
+ }
+ ],
+ "meta": {
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "injected": False
+ },
+ "id": "2e3b85f4-756c-49d9-b34c-f3db13212dbc"
+ },
+ "active": True,
+ "meta": {
+
+ },
+ "details": {
+ "port_filter": True,
+ "ovs_hybrid_plug": True
+ },
+ "preserve_on_delete": False,
+ "qbh_params": None,
+ "ovs_interfaceid": "1f72bd15-8ab2-43cb-94d7-e823dd845255"
+ }
+ ],
+ "object_name": "test",
+ "parent_id": "node-5.cisco.com-instances",
+ "parent_type": "instances_folder",
+ "project_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "projects": [
+ "OSDNA-project"
+ ],
+ "show_in_tree": True,
+ "type": "instance",
+ "uuid": "bf0cb914-b316-486c-a4ce-f22deb453c52"
+}
+
+
+COMPUTE_HOST = {
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-5.cisco.com",
+ "host_type": [
+ "Compute"
+ ],
+ "id": "node-5.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/osdna-zone/node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "name": "node-5.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/osdna-zone/node-5.cisco.com",
+ "object_name": "node-5.cisco.com",
+ "os_id": "1",
+ "parent_id": "osdna-zone",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-compute": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:42.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "osdna-zone"
+}
+
+NETWORK_HOST = {
+ "config": {
+ "interfaces": 4,
+ "log_agent_heartbeats": False,
+ "gateway_external_network_id": "",
+ "router_id": "",
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "ex_gw_ports": 2,
+ "routers": 2,
+ "handle_internal_only_routers": True,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "use_namespaces": True,
+ "agent_mode": "legacy"
+ },
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com",
+ "object_name": "node-6.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:10.000000"
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:54.000000"
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:45.000000"
+ },
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:56.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+}
+
+DUMPXML = "<domain type='qemu' id='38'>\n <name>instance-00000026</name>\n <uuid>bf0cb914-b316-486c-a4ce-f22deb453c52</uuid>\n <metadata>\n <nova:instance xmlns:nova=\"http://openstack.org/xmlns/libvirt/nova/1.0\">\n <nova:package version=\"12.0.0\"/>\n <nova:name>test</nova:name>\n <nova:creationTime>2016-10-17 22:37:43</nova:creationTime>\n <nova:flavor name=\"m1.micro\">\n <nova:memory>64</nova:memory>\n <nova:disk>0</nova:disk>\n <nova:swap>0</nova:swap>\n <nova:ephemeral>0</nova:ephemeral>\n <nova:vcpus>1</nova:vcpus>\n </nova:flavor>\n <nova:owner>\n <nova:user uuid=\"13baa553aae44adca6615e711fd2f6d9\">admin</nova:user>\n <nova:project uuid=\"75c0eb79ff4a42b0ae4973c8375ddf40\">OSDNA-project</nova:project>\n </nova:owner>\n <nova:root type=\"image\" uuid=\"c6f490c4-3656-43c6-8d03-b4e66bd249f9\"/>\n </nova:instance>\n </metadata>\n <memory unit='KiB'>65536</memory>\n <currentMemory unit='KiB'>65536</currentMemory>\n <vcpu placement='static'>1</vcpu>\n <cputune>\n <shares>1024</shares>\n </cputune>\n <sysinfo type='smbios'>\n <system>\n <entry name='manufacturer'>OpenStack Foundation</entry>\n <entry name='product'>OpenStack Nova</entry>\n <entry name='version'>12.0.0</entry>\n <entry name='serial'>9cf57bfd-7477-4671-b2d3-3dfeebfefb1d</entry>\n <entry name='uuid'>bf0cb914-b316-486c-a4ce-f22deb453c52</entry>\n <entry name='family'>Virtual Machine</entry>\n </system>\n </sysinfo>\n <os>\n <type arch='x86_64' machine='pc-i440fx-trusty'>hvm</type>\n <boot dev='hd'/>\n <smbios mode='sysinfo'/>\n </os>\n <features>\n <acpi/>\n <apic/>\n </features>\n <cpu>\n <topology sockets='1' cores='1' threads='1'/>\n </cpu>\n <clock offset='utc'/>\n <on_poweroff>destroy</on_poweroff>\n <on_reboot>restart</on_reboot>\n <on_crash>destroy</on_crash>\n <devices>\n <emulator>/usr/bin/qemu-system-x86_64</emulator>\n <disk type='file' device='disk'>\n <driver name='qemu' type='qcow2' cache='directsync'/>\n <source file='/var/lib/nova/instances/bf0cb914-b316-486c-a4ce-f22deb453c52/disk'/>\n <backingStore type='file' index='1'>\n <format type='raw'/>\n <source file='/var/lib/nova/instances/_base/44881e4441fbd821d0d6240f90742fc97e52f83e'/>\n <backingStore/>\n </backingStore>\n <target dev='vda' bus='virtio'/>\n <alias name='virtio-disk0'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>\n </disk>\n <controller type='usb' index='0'>\n <alias name='usb0'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>\n </controller>\n <controller type='pci' index='0' model='pci-root'>\n <alias name='pci.0'/>\n </controller>\n <interface type='bridge'>\n <mac address='fa:16:3e:e8:7f:04'/>\n <source bridge='qbr1f72bd15-8a'/>\n <target dev='tap1f72bd15-8a'/>\n <model type='virtio'/>\n <driver name='qemu'/>\n <alias name='net0'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>\n </interface>\n <serial type='file'>\n <source path='/var/lib/nova/instances/bf0cb914-b316-486c-a4ce-f22deb453c52/console.log'/>\n <target port='0'/>\n <alias name='serial0'/>\n </serial>\n <serial type='pty'>\n <source path='/dev/pts/8'/>\n <target port='1'/>\n <alias name='serial1'/>\n </serial>\n <console type='file'>\n <source path='/var/lib/nova/instances/bf0cb914-b316-486c-a4ce-f22deb453c52/console.log'/>\n <target type='serial' port='0'/>\n <alias name='serial0'/>\n </console>\n <input type='tablet' bus='usb'>\n <alias name='input0'/>\n </input>\n <input type='mouse' bus='ps2'/>\n <input type='keyboard' bus='ps2'/>\n <graphics type='vnc' port='5902' autoport='yes' listen='0.0.0.0' keymap='en-us'>\n <listen type='address' address='0.0.0.0'/>\n </graphics>\n <video>\n <model type='cirrus' vram='9216' heads='1'/>\n <alias name='video0'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>\n </video>\n <memballoon model='virtio'>\n <alias name='balloon0'/>\n <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>\n <stats period='10'/>\n </memballoon>\n </devices>\n <seclabel type='dynamic' model='apparmor' relabel='yes'>\n <label>libvirt-bf0cb914-b316-486c-a4ce-f22deb453c52</label>\n <imagelabel>libvirt-bf0cb914-b316-486c-a4ce-f22deb453c52</imagelabel>\n </seclabel>\n</domain>\n\n"
+WRONG_DUMPXML = "<domain type='qemu' id='38'><uuid>wrong_instance</uuid></domain>"
+INSTANCES_LIST = [
+ ' Id Name State',
+ '----------------------------------------------------',
+ ' 2 instance-00000002 running',
+ ' 27 instance-0000001c running',
+ ' 38 instance-00000026 running',
+ ' 39 instance-00000028 running',
+ ''
+]
+
+VNIC = {
+ "@type": "bridge",
+ "address": {
+ "@bus": "0x00",
+ "@domain": "0x0000",
+ "@function": "0x0",
+ "@slot": "0x03",
+ "@type": "pci"
+ },
+ "alias": {
+ "@name": "net0"
+ },
+ "driver": {
+ "@name": "qemu"
+ },
+ "mac": {
+ "@address": "fa:16:3e:e8:7f:04"
+ },
+ "model": {
+ "@type": "virtio"
+ },
+ "source": {
+ "@bridge": "qbr1f72bd15-8a"
+ },
+ "target": {
+ "@dev": "tap1f72bd15-8a"
+ }
+}
+
+ID = "38"
+
+VNICS_FROM_DUMP_XML = [
+ {
+ "@type": "bridge",
+ "address": {
+ "@bus": "0x00",
+ "@domain": "0x0000",
+ "@function": "0x0",
+ "@slot": "0x03",
+ "@type": "pci"
+ },
+ "alias": {
+ "@name": "net0"
+ },
+ "driver": {
+ "@name": "qemu"
+ },
+ "host": "node-5.cisco.com",
+ "id": "tap1f72bd15-8a",
+ "instance_db_id": "5806817e4a0a8a3fbe3bee8b",
+ "instance_id": "bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "mac": {
+ "@address": "fa:16:3e:e8:7f:04"
+ },
+ "mac_address": "fa:16:3e:e8:7f:04",
+ "model": {
+ "@type": "virtio"
+ },
+ "name": "tap1f72bd15-8a",
+ "source": {
+ "@bridge": "qbr1f72bd15-8a"
+ },
+ "source_bridge": "qbr1f72bd15-8a",
+ "target": {
+ "@dev": "tap1f72bd15-8a"
+ },
+ "vnic_type": "instance_vnic"
+ }
+]
+
+
+# functional test
+INPUT = "bf0cb914-b316-486c-a4ce-f22deb453c52-vnics" \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors.py
new file mode 100644
index 0000000..f51e510
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors.py
@@ -0,0 +1,103 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+HOST = {
+ "config" : {
+ "metadata_proxy_socket" : "/opt/stack/data/neutron/metadata_proxy",
+ "nova_metadata_ip" : "192.168.20.14",
+ "log_agent_heartbeats" : False
+ },
+ "environment" : "Devstack-VPP-2",
+ "host" : "ubuntu0",
+ "host_type" : [
+ "Controller",
+ "Compute",
+ "Network"
+ ],
+ "id" : "ubuntu0",
+ "id_path" : "/Devstack-VPP-2/Devstack-VPP-2-regions/RegionOne/RegionOne-availability_zones/nova/ubuntu0",
+ "ip_address" : "192.168.20.14",
+ "name" : "ubuntu0",
+ "name_path" : "/Devstack-VPP-2/Regions/RegionOne/Availability Zones/nova/ubuntu0",
+ "object_name" : "ubuntu0",
+ "os_id" : "1",
+ "parent_id" : "nova",
+ "parent_type" : "availability_zone",
+ "services" : {
+ "nova-conductor" : {
+ "available" : True,
+ "active" : True,
+ "updated_at" : "2016-08-30T09:18:58.000000"
+ },
+ "nova-scheduler" : {
+ "available" : True,
+ "active" : True,
+ "updated_at" : "2016-08-30T09:18:54.000000"
+ },
+ "nova-consoleauth" : {
+ "available" : True,
+ "active" : True,
+ "updated_at" : "2016-08-30T09:18:54.000000"
+ }
+ },
+ "show_in_tree" : True,
+ "type" : "host",
+ "zone" : "nova"
+}
+
+WRONG_HOST = {
+ "show_in_tree" : True,
+ "type" : "host",
+ "zone" : "nova"
+}
+
+VCONNECTORS_FOLDER = {
+ "create_object" : True,
+ "environment" : "Mirantis-Liberty-Xiaocong",
+ "id" : "node-6.cisco.com-vconnectors",
+ "id_path" : "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com/node-6.cisco.com-vconnectors",
+ "name" : "vConnectors",
+ "name_path" : "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com/vConnectors",
+ "object_name" : "vConnectors",
+ "parent_id" : "node-6.cisco.com",
+ "parent_type" : "host",
+ "show_in_tree" : True,
+ "text" : "vConnectors",
+ "type" : "vconnectors_folder"
+}
+
+VCONNECTORS = [
+ {
+ "bd_id": "5678",
+ "host": "ubuntu0",
+ "id": "ubuntu0-vconnector-5678",
+ "interfaces": {
+ "name": {
+ "hardware": "VirtualEthernet0/0/8",
+ "id": "15",
+ "mac_address": "fa:16:3e:d1:98:73",
+ "name": "VirtualEthernet0/0/8",
+ "state": "up"
+ }
+ },
+ "interfaces_names": [
+ "TenGigabitEthernetc/0/0",
+ "VirtualEthernet0/0/0",
+ "VirtualEthernet0/0/1",
+ "VirtualEthernet0/0/2",
+ "VirtualEthernet0/0/3",
+ "VirtualEthernet0/0/4",
+ "VirtualEthernet0/0/5",
+ "VirtualEthernet0/0/6",
+ "VirtualEthernet0/0/7",
+ "VirtualEthernet0/0/8"
+ ],
+ "name": "bridge-domain-5678"
+ }
+] \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_ovs.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_ovs.py
new file mode 100644
index 0000000..9161457
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_ovs.py
@@ -0,0 +1,234 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+NETWORK_NODE = {
+ "config": {
+ "interfaces": 4,
+ "log_agent_heartbeats": False,
+ "gateway_external_network_id": "",
+ "router_id": "",
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "ex_gw_ports": 2,
+ "routers": 2,
+ "handle_internal_only_routers": True,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "use_namespaces": True,
+ "agent_mode": "legacy"
+ },
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com",
+ "object_name": "node-6.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:10.000000"
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:54.000000"
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:45.000000"
+ },
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:56.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+}
+
+BRIDGE_RESULT = [
+ "bridge name\tbridge id\t\tSTP enabled\tinterfaces",
+ "br-ex\t\t8000.005056acc9a2\tno\t\teno33554952",
+ "\t\t\t\t\t\t\tp_ff798dba-0",
+ "\t\t\t\t\t\t\tv_public",
+ "\t\t\t\t\t\t\tv_vrouter_pub",
+ "br-fw-admin\t\t8000.005056ace897\tno\t\teno16777728",
+ "br-mesh\t\t8000.005056acc9a2\tno\t\teno33554952.103",
+ "br-mgmt\t\t8000.005056ace897\tno\t\teno16777728.101",
+ "\t\t\t\t\t\t\tmgmt-conntrd",
+ "\t\t\t\t\t\t\tv_management",
+ "\t\t\t\t\t\t\tv_vrouter",
+ "br-storage\t\t8000.005056ace897\tno\t\teno16777728.102"
+]
+
+FIXED_LINES = [
+ "br-ex\t\t8000.005056acc9a2\tno\t\teno33554952,p_ff798dba-0,v_public,v_vrouter_pub",
+ "br-fw-admin\t\t8000.005056ace897\tno\t\teno16777728",
+ "br-mesh\t\t8000.005056acc9a2\tno\t\teno33554952.103",
+ "br-mgmt\t\t8000.005056ace897\tno\t\teno16777728.101,mgmt-conntrd,v_management,v_vrouter",
+ "br-storage\t\t8000.005056ace897\tno\t\teno16777728.102"
+]
+
+PARSE_CM_RESULTS = [
+ {
+ "bridge_id": "8000.005056acc9a2",
+ "bridge_name": "br-ex",
+ "interfaces": "eno33554952,p_ff798dba-0,v_public,v_vrouter_pub",
+ "stp_enabled": "no"
+ },
+ {
+ "bridge_id": "8000.005056ace897",
+ "bridge_name": "br-fw-admin",
+ "interfaces": "eno16777728",
+ "stp_enabled": "no"
+ },
+ {
+ "bridge_id": "8000.005056acc9a2",
+ "bridge_name": "br-mesh",
+ "interfaces": "eno33554952.103",
+ "stp_enabled": "no"
+ },
+ {
+ "bridge_id": "8000.005056ace897",
+ "bridge_name": "br-mgmt",
+ "interfaces": "eno16777728.101,mgmt-conntrd,v_management,v_vrouter",
+ "stp_enabled": "no"
+ },
+ {
+ "bridge_id": "8000.005056ace897",
+ "bridge_name": "br-storage",
+ "interfaces": "eno16777728.102",
+ "stp_enabled": "no"
+ }
+]
+
+# functional test
+INPUT = "node-6.cisco.com"
+OUPUT = [
+ {
+ "connector_type": "bridge",
+ "host": "node-6.cisco.com",
+ "id": "8000.005056acc9a2",
+ "interfaces": {
+ "eno33554952": {
+ "mac_address": "",
+ "name": "eno33554952"
+ },
+ "p_ff798dba-0": {
+ "mac_address": "",
+ "name": "p_ff798dba-0"
+ },
+ "v_public": {
+ "mac_address": "",
+ "name": "v_public"
+ },
+ "v_vrouter_pub": {
+ "mac_address": "",
+ "name": "v_vrouter_pub"
+ }
+ },
+ "interfaces_names": [
+ "p_ff798dba-0",
+ "v_public",
+ "v_vrouter_pub",
+ "eno33554952"
+ ],
+ "name": "br-ex",
+ "stp_enabled": "no"
+ },
+ {
+ "connector_type": "bridge",
+ "host": "node-6.cisco.com",
+ "id": "8000.005056ace897",
+ "interfaces": {
+ "eno16777728": {
+ "mac_address": "",
+ "name": "eno16777728"
+ }
+ },
+ "interfaces_names": [
+ "eno16777728"
+ ],
+ "name": "br-fw-admin",
+ "stp_enabled": "no"
+ },
+ {
+ "connector_type": "bridge",
+ "host": "node-6.cisco.com",
+ "id": "8000.005056acc9a2",
+ "interfaces": {
+ "eno33554952.103": {
+ "mac_address": "",
+ "name": "eno33554952.103"
+ }
+ },
+ "interfaces_names": [
+ "eno33554952.103"
+ ],
+ "name": "br-mesh",
+ "stp_enabled": "no"
+ },
+ {
+ "connector_type": "bridge",
+ "host": "node-6.cisco.com",
+ "id": "8000.005056ace897",
+ "interfaces": {
+ "eno16777728.101": {
+ "mac_address": "",
+ "name": "eno16777728.101"
+ },
+ "mgmt-conntrd": {
+ "mac_address": "",
+ "name": "mgmt-conntrd"
+ },
+ "v_management": {
+ "mac_address": "",
+ "name": "v_management"
+ },
+ "v_vrouter": {
+ "mac_address": "",
+ "name": "v_vrouter"
+ }
+ },
+ "interfaces_names": [
+ "v_management",
+ "mgmt-conntrd",
+ "v_vrouter",
+ "eno16777728.101"
+ ],
+ "name": "br-mgmt",
+ "stp_enabled": "no"
+ },
+ {
+ "connector_type": "bridge",
+ "host": "node-6.cisco.com",
+ "id": "8000.005056ace897",
+ "interfaces": {
+ "eno16777728.102": {
+ "mac_address": "",
+ "name": "eno16777728.102"
+ }
+ },
+ "interfaces_names": [
+ "eno16777728.102"
+ ],
+ "name": "br-storage",
+ "stp_enabled": "no"
+ }
+] \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_vpp.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_vpp.py
new file mode 100644
index 0000000..2c78b6a
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_vconnectors_vpp.py
@@ -0,0 +1,137 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+HOST = {
+ "config" : {
+ "metadata_proxy_socket" : "/opt/stack/data/neutron/metadata_proxy",
+ "nova_metadata_ip" : "192.168.20.14",
+ "log_agent_heartbeats" : False
+ },
+ "environment" : "Devstack-VPP-2",
+ "host" : "ubuntu0",
+ "host_type" : [
+ "Controller",
+ "Compute",
+ "Network"
+ ],
+ "id" : "ubuntu0",
+ "id_path" : "/Devstack-VPP-2/Devstack-VPP-2-regions/RegionOne/RegionOne-availability_zones/nova/ubuntu0",
+ "ip_address" : "192.168.20.14",
+ "name" : "ubuntu0",
+ "name_path" : "/Devstack-VPP-2/Regions/RegionOne/Availability Zones/nova/ubuntu0",
+ "object_name" : "ubuntu0",
+ "os_id" : "1",
+ "parent_id" : "nova",
+ "parent_type" : "availability_zone",
+ "services" : {
+ "nova-conductor" : {
+ "available" : True,
+ "active" : True,
+ "updated_at" : "2016-08-30T09:18:58.000000"
+ },
+ "nova-scheduler" : {
+ "available" : True,
+ "active" : True,
+ "updated_at" : "2016-08-30T09:18:54.000000"
+ },
+ "nova-consoleauth" : {
+ "available" : True,
+ "active" : True,
+ "updated_at" : "2016-08-30T09:18:54.000000"
+ }
+ },
+ "show_in_tree" : True,
+ "type" : "host",
+ "zone" : "nova"
+}
+
+MODE_RESULT = [
+ "l3 local0 ",
+ "l3 pg/stream-0 ",
+ "l3 pg/stream-1 ",
+ "l3 pg/stream-2 ",
+ "l3 pg/stream-3 ",
+ "l2 bridge TenGigabitEthernetc/0/0 bd_id 5678 shg 0",
+ "l3 TenGigabitEthernetd/0/0 ",
+ "l2 bridge VirtualEthernet0/0/0 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/1 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/2 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/3 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/4 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/5 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/6 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/7 bd_id 5678 shg 0",
+ "l2 bridge VirtualEthernet0/0/8 bd_id 5678 shg 0"
+]
+
+INTERFACE_LINES = [
+ " Name Idx Link Hardware",
+ "TenGigabitEthernetc/0/0 5 up TenGigabitEthernetc/0/0",
+ " Ethernet address 00:25:b5:99:00:5c",
+ " Cisco VIC",
+ " carrier up full duplex speed 40000 mtu 1500 promisc",
+ " rx queues 1, rx desc 5120, tx queues 1, tx desc 2048",
+ " cpu socket 0",
+ "",
+ " tx frames ok 81404",
+ " tx bytes ok 6711404",
+ " rx frames ok 502521",
+ " rx bytes ok 668002732",
+ " rx missed 64495",
+ " extended stats:",
+ " rx good packets 502521",
+ " tx good packets 81404",
+ " rx good bytes 668002732",
+ " tx good bytes 6711404"
+]
+
+INTERFACE_NAME = "TenGigabitEthernetc/0/0"
+
+GET_INTERFACE_DETAIL = {
+ "hardware": "TenGigabitEthernetc/0/0",
+ "id": "5",
+ "mac_address": "00:25:b5:99:00:5c",
+ "name": "TenGigabitEthernetc/0/0",
+ "state": "up"
+}
+
+# functional test
+# environment: Devstack-VPP-2
+# inventory name: vpp
+
+INPUT = "ubuntu0"
+OUPUT = [
+ {
+ "bd_id": "5678",
+ "host": "ubuntu0",
+ "id": "ubuntu0-vconnector-5678",
+ "interfaces": {
+ "name": {
+ "hardware": "VirtualEthernet0/0/8",
+ "id": "15",
+ "mac_address": "fa:16:3e:d1:98:73",
+ "name": "VirtualEthernet0/0/8",
+ "state": "up"
+ }
+ },
+ "interfaces_names": [
+ "TenGigabitEthernetc/0/0",
+ "VirtualEthernet0/0/0",
+ "VirtualEthernet0/0/1",
+ "VirtualEthernet0/0/2",
+ "VirtualEthernet0/0/3",
+ "VirtualEthernet0/0/4",
+ "VirtualEthernet0/0/5",
+ "VirtualEthernet0/0/6",
+ "VirtualEthernet0/0/7",
+ "VirtualEthernet0/0/8"
+ ],
+ "name": "bridge-domain-5678"
+ }
+] \ No newline at end of file
diff --git a/app/test/fetch/cli_fetch/test_data/cli_fetch_vservice_vnics.py b/app/test/fetch/cli_fetch/test_data/cli_fetch_vservice_vnics.py
new file mode 100644
index 0000000..0b60af5
--- /dev/null
+++ b/app/test/fetch/cli_fetch/test_data/cli_fetch_vservice_vnics.py
@@ -0,0 +1,616 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+NETWORK_NODE = {
+ "config": {
+ "interfaces": 4,
+ "log_agent_heartbeats": False,
+ "gateway_external_network_id": "",
+ "router_id": "",
+ "interface_driver": "neutron.agent.linux.interface.OVSInterfaceDriver",
+ "ex_gw_ports": 2,
+ "routers": 2,
+ "handle_internal_only_routers": True,
+ "floating_ips": 1,
+ "external_network_bridge": "",
+ "use_namespaces": True,
+ "agent_mode": "legacy"
+ },
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com",
+ "name": "node-6.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com",
+ "object_name": "node-6.cisco.com",
+ "parent_id": "internal",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-scheduler": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:10.000000"
+ },
+ "nova-consoleauth": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:54.000000"
+ },
+ "nova-conductor": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:45.000000"
+ },
+ "nova-cert": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:56.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "internal"
+}
+
+COMPUTE_NODE = {
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-5.cisco.com",
+ "host_type": [
+ "Compute"
+ ],
+ "id": "node-5.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/osdna-zone/node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "name": "node-5.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/osdna-zone/node-5.cisco.com",
+ "object_name": "node-5.cisco.com",
+ "os_id": "1",
+ "parent_id": "osdna-zone",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-compute": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:42.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "osdna-zone"
+}
+
+ERROR_NODE = {
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-5.cisco.com",
+ "id": "node-5.cisco.com",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/osdna-zone/node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "name": "node-5.cisco.com",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/osdna-zone/node-5.cisco.com",
+ "object_name": "node-5.cisco.com",
+ "os_id": "1",
+ "parent_id": "osdna-zone",
+ "parent_type": "availability_zone",
+ "services": {
+ "nova-compute": {
+ "active": True,
+ "available": True,
+ "updated_at": "2016-10-21T18:01:42.000000"
+ }
+ },
+ "show_in_tree": True,
+ "type": "host",
+ "zone": "osdna-zone"
+}
+
+NAME_SPACES = [
+ 'qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17',
+ 'qdhcp-0abe6331-0d74-4bbd-ad89-a5719c3793e4',
+ 'qdhcp-413de095-01ed-49dc-aa50-4479f43d390e',
+ 'qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc',
+ 'qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe',
+ 'qdhcp-eb276a62-15a9-4616-a192-11466fdd147f',
+ 'qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627',
+ 'qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f',
+ 'qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc',
+ 'qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9',
+ 'qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6',
+ 'haproxy',
+ 'vrouter'
+]
+
+SERVICE_ID = 'qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17'
+
+SERVICES = [
+ {
+ "IP Address": "172.16.13.2",
+ "IPv6 Address": "fe80::f816:3eff:fea1:eb73/64",
+ "cidr": "172.16.13.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:a1:eb:73\ninet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fea1:eb73/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:28 errors:0 dropped:35 overruns:0 frame:0\nTX packets:8 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:4485 (4.4 KB) TX bytes:648 (648.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "tapa68b2627-a1",
+ "mac_address": "fa:16:3e:a1:eb:73",
+ "master_parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "master_parent_type": "vservice",
+ "name": "tapa68b2627-a1",
+ "netmask": "255.255.255.0",
+ "network": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ }
+]
+
+NET_MASK_ARRAY = ["255", "255", "255", "0"]
+SIZE = '24'
+
+VNIC = {
+ "IP Address": "172.16.13.2",
+ "IPv6 Address": "fe80::f816:3eff:fea1:eb73/64",
+ "host": "node-6.cisco.com",
+ "id": "tapa68b2627-a1",
+ "lines": [
+ "Link encap:Ethernet HWaddr fa:16:3e:a1:eb:73",
+ "inet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0",
+ "inet6 addr: fe80::f816:3eff:fea1:eb73/64 Scope:Link",
+ "UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1",
+ "RX packets:28 errors:0 dropped:35 overruns:0 frame:0",
+ "TX packets:8 errors:0 dropped:0 overruns:0 carrier:0",
+ "collisions:0 txqueuelen:0",
+ "RX bytes:4485 (4.4 KB) TX bytes:648 (648.0 B)",
+ ""
+ ],
+ "mac_address": "fa:16:3e:a1:eb:73",
+ "master_parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "master_parent_type": "vservice",
+ "name": "tapa68b2627-a1",
+ "netmask": "255.255.255.0",
+ "parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+}
+
+RAW_VNIC = {
+ "host": "node-6.cisco.com",
+ "id": "tapa68b2627-a1",
+ "lines": [],
+ "master_parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "master_parent_type": "vservice",
+ "name": "tapa68b2627-a1",
+ "parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+}
+
+NETWORK = [{
+ "admin_state_up": True,
+ "cidrs": [
+ "172.16.13.0/24"
+ ],
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "id": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-projects/75c0eb79ff4a42b0ae4973c8375ddf40/75c0eb79ff4a42b0ae4973c8375ddf40-networks/8673c48a-f137-4497-b25d-08b7b218fd17",
+ "mtu": 1400,
+ "name": "25",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Projects/OSDNA-project/Networks/25",
+ "network": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "object_name": "25",
+ "parent_id": "75c0eb79ff4a42b0ae4973c8375ddf40-networks",
+ "parent_text": "Networks",
+ "parent_type": "networks_folder",
+ "port_security_enabled": True,
+ "project": "OSDNA-project",
+ "provider:network_type": "vxlan",
+ "provider:physical_network": None,
+ "provider:segmentation_id": 52,
+ "router:external": False,
+ "shared": False,
+ "show_in_tree": True,
+ "status": "ACTIVE",
+ "subnets": {
+ "123e": {
+ "ip_version": 4,
+ "enable_dhcp": True,
+ "gateway_ip": "172.16.13.1",
+ "id": "fcfa62ec-5ae7-46ce-9259-5f30de7af858",
+ "ipv6_ra_mode": None,
+ "name": "123e",
+ "dns_nameservers": [
+
+ ],
+ "cidr" : "172.16.13.0/24",
+ "subnetpool_id": None,
+ "ipv6_address_mode": None,
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "network_id": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "host_routes": [
+
+ ],
+ "allocation_pools": [
+ {
+ "start": "172.16.13.2",
+ "end": "172.16.13.254"
+ }
+ ]
+ }
+ },
+ "tenant_id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "type": "network"
+}]
+
+VSERVICE = {
+ "children_url": "/osdna_dev/discover.py?type=tree&id=qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "environment": "Mirantis-Liberty-Xiaocong",
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "id_path": "/Mirantis-Liberty-Xiaocong/Mirantis-Liberty-Xiaocong-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com/node-6.cisco.com-vservices/node-6.cisco.com-vservices-dhcps/qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "local_service_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "name": "dhcp-25",
+ "name_path": "/Mirantis-Liberty-Xiaocong/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com/Vservices/DHCP servers/dhcp-25",
+ "network": [
+ "8673c48a-f137-4497-b25d-08b7b218fd17"
+ ],
+ "object_name": "dhcp-25",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp",
+ "show_in_tree": True,
+ "type": "vservice"
+}
+
+
+CIDR = "172.16.13.0/24"
+
+IFCONFIG_RESULT = [
+ "lo Link encap:Local Loopback ",
+ " inet addr:127.0.0.1 Mask:255.0.0.0",
+ " inet6 addr: ::1/128 Scope:Host",
+ " UP LOOPBACK RUNNING MTU:65536 Metric:1",
+ " RX packets:0 errors:0 dropped:0 overruns:0 frame:0",
+ " TX packets:0 errors:0 dropped:0 overruns:0 carrier:0",
+ " collisions:0 txqueuelen:0 ",
+ " RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)",
+ "",
+ "tapa68b2627-a1 Link encap:Ethernet HWaddr fa:16:3e:a1:eb:73 ",
+ " inet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0",
+ " inet6 addr: fe80::f816:3eff:fea1:eb73/64 Scope:Link",
+ " UP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1",
+ " RX packets:28 errors:0 dropped:35 overruns:0 frame:0",
+ " TX packets:8 errors:0 dropped:0 overruns:0 carrier:0",
+ " collisions:0 txqueuelen:0 ",
+ " RX bytes:4485 (4.4 KB) TX bytes:648 (648.0 B)",
+ ""
+]
+
+MAC_ADDRESS_LINE = "tapa68b2627-a1 Link encap:Ethernet HWaddr 00:50:56:ac:e8:97 "
+MAC_ADDRESS = "00:50:56:ac:e8:97"
+IPV6_ADDRESS_LINE = " inet6 addr: fe80::f816:3eff:fea1:eb73/64 Scope:Link"
+IPV6_ADDRESS = "fe80::f816:3eff:fea1:eb73/64"
+IPV4_ADDRESS_LINE = " inet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0"
+IPV4_ADDRESS = "172.16.13.2"
+
+# functional test
+INPUT = "node-6.cisco.com"
+OUTPUT = [
+ {
+ "IP Address": "172.16.13.2",
+ "IPv6 Address": "fe80::f816:3eff:fea1:eb73/64",
+ "cidr": "172.16.13.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:a1:eb:73\ninet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fea1:eb73/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:28 errors:0 dropped:35 overruns:0 frame:0\nTX packets:8 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:4485 (4.4 KB) TX bytes:648 (648.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "tapa68b2627-a1",
+ "mac_address": "fa:16:3e:a1:eb:73",
+ "master_parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17",
+ "master_parent_type": "vservice",
+ "name": "tapa68b2627-a1",
+ "netmask": "255.255.255.0",
+ "network": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "parent_id": "qdhcp-8673c48a-f137-4497-b25d-08b7b218fd17-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.12.2",
+ "IPv6 Address": "fe80::f816:3eff:fec1:7f19/64",
+ "cidr": "172.16.12.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:c1:7f:19\ninet addr:172.16.12.2 Bcast:172.16.12.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fec1:7f19/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:6 errors:0 dropped:8 overruns:0 frame:0\nTX packets:8 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:360 (360.0 B) TX bytes:648 (648.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "tape67d81de-48",
+ "mac_address": "fa:16:3e:c1:7f:19",
+ "master_parent_id": "qdhcp-0abe6331-0d74-4bbd-ad89-a5719c3793e4",
+ "master_parent_type": "vservice",
+ "name": "tape67d81de-48",
+ "netmask": "255.255.255.0",
+ "network": "0abe6331-0d74-4bbd-ad89-a5719c3793e4",
+ "parent_id": "qdhcp-0abe6331-0d74-4bbd-ad89-a5719c3793e4-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.10.2",
+ "IPv6 Address": "fe80::f816:3eff:fe23:1b94/64",
+ "cidr": "172.16.10.0/25",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:23:1b:94\ninet addr:172.16.10.2 Bcast:172.16.10.127 Mask:255.255.255.128\ninet6 addr: fe80::f816:3eff:fe23:1b94/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:51 errors:0 dropped:12 overruns:0 frame:0\nTX packets:8 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:9161 (9.1 KB) TX bytes:648 (648.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "tapa1bf631f-de",
+ "mac_address": "fa:16:3e:23:1b:94",
+ "master_parent_id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "master_parent_type": "vservice",
+ "name": "tapa1bf631f-de",
+ "netmask": "255.255.255.128",
+ "network": "413de095-01ed-49dc-aa50-4479f43d390e",
+ "parent_id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.13.2",
+ "IPv6 Address": "fe80::f816:3eff:fec3:c871/64",
+ "cidr": "172.16.13.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:c3:c8:71\ninet addr:172.16.13.2 Bcast:172.16.13.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fec3:c871/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:4614 errors:0 dropped:4 overruns:0 frame:0\nTX packets:4459 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:823296 (823.2 KB) TX bytes:929712 (929.7 KB)\n",
+ "host": "node-6.cisco.com",
+ "id": "tapaf69959f-ef",
+ "mac_address": "fa:16:3e:c3:c8:71",
+ "master_parent_id": "qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc",
+ "master_parent_type": "vservice",
+ "name": "tapaf69959f-ef",
+ "netmask": "255.255.255.0",
+ "network": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "parent_id": "qdhcp-2e3b85f4-756c-49d9-b34c-f3db13212dbc-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.4.2",
+ "IPv6 Address": "fe80::f816:3eff:fed7:c516/64",
+ "cidr": "172.16.4.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:d7:c5:16\ninet addr:172.16.4.2 Bcast:172.16.4.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fed7:c516/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:56928 errors:0 dropped:15 overruns:0 frame:0\nTX packets:56675 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:10526014 (10.5 MB) TX bytes:12041070 (12.0 MB)\n",
+ "host": "node-6.cisco.com",
+ "id": "tap16620a58-c4",
+ "mac_address": "fa:16:3e:d7:c5:16",
+ "master_parent_id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "master_parent_type": "vservice",
+ "name": "tap16620a58-c4",
+ "netmask": "255.255.255.0",
+ "network": "b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe",
+ "parent_id": "qdhcp-b6fd5175-4b22-4256-9b1a-9fc4b9dce1fe-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.2.2",
+ "IPv6 Address": "fe80::f816:3eff:feeb:39c2/64",
+ "cidr": "172.16.2.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:eb:39:c2\ninet addr:172.16.2.2 Bcast:172.16.2.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:feeb:39c2/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:93317 errors:0 dropped:57 overruns:0 frame:0\nTX packets:93264 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:17406098 (17.4 MB) TX bytes:19958079 (19.9 MB)\n",
+ "host": "node-6.cisco.com",
+ "id": "tap82d4992f-4d",
+ "mac_address": "fa:16:3e:eb:39:c2",
+ "master_parent_id": "qdhcp-eb276a62-15a9-4616-a192-11466fdd147f",
+ "master_parent_type": "vservice",
+ "name": "tap82d4992f-4d",
+ "netmask": "255.255.255.0",
+ "network": "eb276a62-15a9-4616-a192-11466fdd147f",
+ "parent_id": "qdhcp-eb276a62-15a9-4616-a192-11466fdd147f-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.3.2",
+ "IPv6 Address": "fe80::f816:3eff:fe1c:9936/64",
+ "cidr": "172.16.3.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:1c:99:36\ninet addr:172.16.3.2 Bcast:172.16.3.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe1c:9936/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:170894 errors:0 dropped:41 overruns:0 frame:0\nTX packets:170588 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:31784458 (31.7 MB) TX bytes:36444046 (36.4 MB)\n",
+ "host": "node-6.cisco.com",
+ "id": "tap5f22f397-d8",
+ "mac_address": "fa:16:3e:1c:99:36",
+ "master_parent_id": "qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627",
+ "master_parent_type": "vservice",
+ "name": "tap5f22f397-d8",
+ "netmask": "255.255.255.0",
+ "network": "7e59b726-d6f4-451a-a574-c67a920ff627",
+ "parent_id": "qdhcp-7e59b726-d6f4-451a-a574-c67a920ff627-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.1.2",
+ "IPv6 Address": "fe80::f816:3eff:fe59:5fff/64",
+ "cidr": "172.16.1.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:59:5f:ff\ninet addr:172.16.1.2 Bcast:172.16.1.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe59:5fff/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:93468 errors:0 dropped:38 overruns:0 frame:0\nTX packets:93452 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:17416578 (17.4 MB) TX bytes:19972565 (19.9 MB)\n",
+ "host": "node-6.cisco.com",
+ "id": "tapbf16c3ab-56",
+ "mac_address": "fa:16:3e:59:5f:ff",
+ "master_parent_id": "qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "master_parent_type": "vservice",
+ "name": "tapbf16c3ab-56",
+ "netmask": "255.255.255.0",
+ "network": "a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "parent_id": "qdhcp-a55ff1e8-3821-4e5f-bcfd-07df93720a4f-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "192.168.111.2",
+ "IPv6 Address": "fe80::f816:3eff:fe74:5/64",
+ "cidr": "192.168.111.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:74:00:05\ninet addr:192.168.111.2 Bcast:192.168.111.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe74:5/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:45 errors:0 dropped:28 overruns:0 frame:0\nTX packets:8 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:3734 (3.7 KB) TX bytes:648 (648.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "tapee8e5dbb-03",
+ "mac_address": "fa:16:3e:74:00:05",
+ "master_parent_id": "qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc",
+ "master_parent_type": "vservice",
+ "name": "tapee8e5dbb-03",
+ "netmask": "255.255.255.0",
+ "network": "6504fcf7-41d7-40bb-aeb1-6a7658c105fc",
+ "parent_id": "qdhcp-6504fcf7-41d7-40bb-aeb1-6a7658c105fc-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.0.131",
+ "IPv6 Address": "2001:420:4482:24c1:f816:3eff:fe23:3ad7/64",
+ "cidr": "172.16.0.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:23:3a:d7\ninet addr:172.16.0.131 Bcast:172.16.0.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe23:3ad7/64 Scope:Link\ninet6 addr: 2001:420:4482:24c1:f816:3eff:fe23:3ad7/64 Scope:Global\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:48172796 errors:0 dropped:1144801 overruns:0 frame:0\nTX packets:63 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:4220491940 (4.2 GB) TX bytes:3162 (3.1 KB)\n",
+ "host": "node-6.cisco.com",
+ "id": "qg-63489f34-af",
+ "mac_address": "fa:16:3e:23:3a:d7",
+ "master_parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "master_parent_type": "vservice",
+ "name": "qg-63489f34-af",
+ "netmask": "255.255.255.0",
+ "network": "c64adb76-ad9d-4605-9f5e-bd6dbe325cfb",
+ "parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.13.5",
+ "IPv6 Address": "fe80::f816:3eff:fe1f:e174/64",
+ "cidr": "172.16.13.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:1f:e1:74\ninet addr:172.16.13.5 Bcast:172.16.13.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe1f:e174/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:25 errors:0 dropped:1 overruns:0 frame:0\nTX packets:10 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:2460 (2.4 KB) TX bytes:864 (864.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "qr-18f029db-77",
+ "mac_address": "fa:16:3e:1f:e1:74",
+ "master_parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "master_parent_type": "vservice",
+ "name": "qr-18f029db-77",
+ "netmask": "255.255.255.0",
+ "network": "8673c48a-f137-4497-b25d-08b7b218fd17",
+ "parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.2.1",
+ "IPv6 Address": "fe80::f816:3eff:fe2c:fb9b/64",
+ "cidr": "172.16.2.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:2c:fb:9b\ninet addr:172.16.2.1 Bcast:172.16.2.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe2c:fb9b/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:49 errors:0 dropped:3 overruns:0 frame:0\nTX packets:10 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:5825 (5.8 KB) TX bytes:864 (864.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "qr-3ff411a2-54",
+ "mac_address": "fa:16:3e:2c:fb:9b",
+ "master_parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "master_parent_type": "vservice",
+ "name": "qr-3ff411a2-54",
+ "netmask": "255.255.255.0",
+ "network": "eb276a62-15a9-4616-a192-11466fdd147f",
+ "parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.1.1",
+ "IPv6 Address": "fe80::f816:3eff:feee:9a46/64",
+ "cidr": "172.16.1.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:ee:9a:46\ninet addr:172.16.1.1 Bcast:172.16.1.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:feee:9a46/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:85 errors:0 dropped:14 overruns:0 frame:0\nTX packets:10 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:7402 (7.4 KB) TX bytes:864 (864.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "qr-8733cc5d-b3",
+ "mac_address": "fa:16:3e:ee:9a:46",
+ "master_parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "master_parent_type": "vservice",
+ "name": "qr-8733cc5d-b3",
+ "netmask": "255.255.255.0",
+ "network": "a55ff1e8-3821-4e5f-bcfd-07df93720a4f",
+ "parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.3.1",
+ "IPv6 Address": "fe80::f816:3eff:feba:5a3c/64",
+ "cidr": "172.16.3.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:ba:5a:3c\ninet addr:172.16.3.1 Bcast:172.16.3.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:feba:5a3c/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:3018 errors:0 dropped:15 overruns:0 frame:0\nTX packets:1766 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:295458 (295.4 KB) TX bytes:182470 (182.4 KB)\n",
+ "host": "node-6.cisco.com",
+ "id": "qr-bb9b8340-72",
+ "mac_address": "fa:16:3e:ba:5a:3c",
+ "master_parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9",
+ "master_parent_type": "vservice",
+ "name": "qr-bb9b8340-72",
+ "netmask": "255.255.255.0",
+ "network": "7e59b726-d6f4-451a-a574-c67a920ff627",
+ "parent_id": "qrouter-9ec3d703-0725-47e3-8f48-02b16236caf9-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "172.16.0.130",
+ "IPv6 Address": "fe80::f816:3eff:fecb:8d7b/64",
+ "cidr": "172.16.0.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:cb:8d:7b\ninet addr:172.16.0.130 Bcast:172.16.0.255 Mask:255.255.255.0\ninet6 addr: 2001:420:4482:24c1:f816:3eff:fecb:8d7b/64 Scope:Global\ninet6 addr: fe80::f816:3eff:fecb:8d7b/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:48172955 errors:0 dropped:1144729 overruns:0 frame:0\nTX packets:59 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:4220505032 (4.2 GB) TX bytes:2958 (2.9 KB)\n",
+ "host": "node-6.cisco.com",
+ "id": "qg-57e65d34-3d",
+ "mac_address": "fa:16:3e:cb:8d:7b",
+ "master_parent_id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6",
+ "master_parent_type": "vservice",
+ "name": "qg-57e65d34-3d",
+ "netmask": "255.255.255.0",
+ "network": "c64adb76-ad9d-4605-9f5e-bd6dbe325cfb",
+ "parent_id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ },
+ {
+ "IP Address": "192.168.111.1",
+ "IPv6 Address": "fe80::f816:3eff:fe0a:3cc/64",
+ "cidr": "192.168.111.0/24",
+ "data": "Link encap:Ethernet HWaddr fa:16:3e:0a:03:cc\ninet addr:192.168.111.1 Bcast:192.168.111.255 Mask:255.255.255.0\ninet6 addr: fe80::f816:3eff:fe0a:3cc/64 Scope:Link\nUP BROADCAST RUNNING MULTICAST MTU:1450 Metric:1\nRX packets:79 errors:0 dropped:0 overruns:0 frame:0\nTX packets:10 errors:0 dropped:0 overruns:0 carrier:0\ncollisions:0 txqueuelen:0\nRX bytes:6475 (6.4 KB) TX bytes:864 (864.0 B)\n",
+ "host": "node-6.cisco.com",
+ "id": "qr-f7b44150-99",
+ "mac_address": "fa:16:3e:0a:03:cc",
+ "master_parent_id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6",
+ "master_parent_type": "vservice",
+ "name": "qr-f7b44150-99",
+ "netmask": "255.255.255.0",
+ "network": "6504fcf7-41d7-40bb-aeb1-6a7658c105fc",
+ "parent_id": "qrouter-49ac7716-06da-49ed-b388-f8ba60e8a0e6-vnics",
+ "parent_text": "vNICs",
+ "parent_type": "vnics_folder",
+ "type": "vnic",
+ "vnic_type": "vservice_vnic"
+ }
+] \ No newline at end of file
diff --git a/app/test/fetch/config/__init__.py b/app/test/fetch/config/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/config/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/config/test_config.py b/app/test/fetch/config/test_config.py
new file mode 100644
index 0000000..176fd48
--- /dev/null
+++ b/app/test/fetch/config/test_config.py
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+# local config info for test.
+
+
+MONGODB_CONFIG = 'your-mongo-config-path-here'
+
+ENV_CONFIG = 'your-env-name-here'
+
+COLLECTION_CONFIG = 'your-inventory-collection-name-here'
diff --git a/app/test/fetch/db_fetch/__init__.py b/app/test/fetch/db_fetch/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/db_fetch/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/db_fetch/mock_cursor.py b/app/test/fetch/db_fetch/mock_cursor.py
new file mode 100644
index 0000000..71efd3b
--- /dev/null
+++ b/app/test/fetch/db_fetch/mock_cursor.py
@@ -0,0 +1,25 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+class MockCursor:
+
+ def __init__(self, result):
+ self.result = result
+ self.current = 0
+
+ def __next__(self):
+ if self.current < len(self.result):
+ next = self.result[self.current]
+ self.current += 1
+ return next
+ else:
+ raise StopIteration
+
+ def __iter__(self):
+ return self
diff --git a/app/test/fetch/db_fetch/test_data/__init__.py b/app/test/fetch/db_fetch/test_data/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/fetch/db_fetch/test_data/db_access.py b/app/test/fetch/db_fetch/test_data/db_access.py
new file mode 100644
index 0000000..a4ad548
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_access.py
@@ -0,0 +1,40 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+DB_CONFIG = {
+ "host": "10.56.20.239",
+ "name": "mysql",
+ "password": "102QreDdiD5sKcvNf9qbHrmr",
+ "port": 3307.0,
+ "user": "root",
+ "schema": "nova"
+ }
+
+QUERY_WITHOUT_ID = """
+ SELECT id, name
+ FROM nova.aggregates
+ WHERE deleted = 0
+ """
+
+QUERY_WITH_ID = """
+ SELECT CONCAT('aggregate-', a.name, '-', host) AS id, host AS name
+ FROM nova.aggregate_hosts ah
+ JOIN nova.aggregates a ON a.id = ah.aggregate_id
+ WHERE ah.deleted = 0 AND aggregate_id = %s
+ """
+
+ID = "2"
+OBJECT_TYPE = "host aggregate"
+
+OBJECTS_LIST = [
+ {
+ "id": 1,
+ "name": "osdna-agg"
+ }
+]
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_aggregate_hosts.py b/app/test/fetch/db_fetch/test_data/db_fetch_aggregate_hosts.py
new file mode 100644
index 0000000..2f1313a
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_aggregate_hosts.py
@@ -0,0 +1,34 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from bson.objectid import ObjectId
+
+
+AGGREGATE = {
+ "id": "1",
+}
+
+HOSTS = [
+ {
+ "id": "aggregate-osdna-agg-node-5.cisco.com",
+ "name": "node-5.cisco.com"
+ }
+]
+
+HOST_IN_INVENTORY = {
+ "_id": "595ac4b6d7c037efdb8918a7"
+}
+
+HOSTS_RESULT = [
+ {
+ "id": "aggregate-osdna-agg-node-5.cisco.com",
+ "name": "node-5.cisco.com",
+ "ref_id": ObjectId(HOST_IN_INVENTORY["_id"])
+ }
+]
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_aggregates.py b/app/test/fetch/db_fetch/test_data/db_fetch_aggregates.py
new file mode 100644
index 0000000..65182fa
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_aggregates.py
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+REGION_ID = "RegionOne"
+
+OBJECTS_LIST = [
+ {
+ "id": 1,
+ "name": "calipso-agg"
+ }
+]
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_host_network_agents.py b/app/test/fetch/db_fetch/test_data/db_fetch_host_network_agents.py
new file mode 100644
index 0000000..6188ddf
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_host_network_agents.py
@@ -0,0 +1,65 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+CONFIG_WITH_MECHANISM_DRIVERS = {
+ 'mechanism_drivers': [
+ "OVS"
+ ]
+}
+
+CONFIG_WITHOUT_MECHANISM_DRIVERS = {
+ 'mechanism_drivers': [
+
+ ]
+}
+
+NETWORK_AGENT_FOLDER_ID = 'node-6.cisco.com-network_agents'
+
+NETWORK_AGENT = [
+ {
+ 'configurations': '{}',
+ 'id': '1764430c-c09e-4717-86fa-c04350b1fcbb',
+ 'binary': 'neutron-openvswitch-agent',
+ },
+ {
+ 'configurations': '{}',
+ 'id': '2c2ddfee-91f9-47da-bd65-aceecd998b7c',
+ 'binary': 'neutron-dhcp-agent',
+ }
+]
+
+NETWORK_AGENT_WITH_MECHANISM_DRIVERS_IN_CONFIG_RESULTS = [
+ {
+ 'configurations': {},
+ 'id': 'OVS-1764430c-c09e-4717-86fa-c04350b1fcbb',
+ 'binary': 'neutron-openvswitch-agent',
+ 'name': 'neutron-openvswitch-agent'
+ },
+ {
+ 'configurations': {},
+ 'id': 'OVS-2c2ddfee-91f9-47da-bd65-aceecd998b7c',
+ 'binary': 'neutron-dhcp-agent',
+ 'name': 'neutron-dhcp-agent'
+ }
+]
+
+NETWORK_AGENT_WITHOUT_MECHANISM_DRIVERS_IN_CONFIG_RESULTS = [
+ {
+ 'configurations': {},
+ 'id': 'network_agent-1764430c-c09e-4717-86fa-c04350b1fcbb',
+ 'binary': 'neutron-openvswitch-agent',
+ 'name': 'neutron-openvswitch-agent'
+ },
+ {
+ 'configurations': {},
+ 'id': 'network_agent-2c2ddfee-91f9-47da-bd65-aceecd998b7c',
+ 'binary': 'neutron-dhcp-agent',
+ 'name': 'neutron-dhcp-agent'
+ }
+]
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_instances.py b/app/test/fetch/db_fetch/test_data/db_fetch_instances.py
new file mode 100644
index 0000000..5ba6a74
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_instances.py
@@ -0,0 +1,91 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+INSTANCES_FROM_API = [
+ {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ }
+]
+
+INSTANCES_FROM_DB = [
+ {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "network_info": "[{\"network\": {\"id\": \"7e59b726-d6f4-451a-a574-c67a920ff627\"}}]",
+ "project": "Calipso-project",
+ },
+ {
+ "host": "node-5.cisco.com",
+ "id": "bf0cb914-b316-486c-a4ce-f22deb453c52",
+ "network_info": "[{\"network\": {\"id\": \"7e59b726-d6f4-451a-a574-c67a920ff627\"}}]",
+ "project": "Calipso-project",
+ }
+]
+
+UPDATED_INSTANCES_DATA = [
+ {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "network": ["7e59b726-d6f4-451a-a574-c67a920ff627"],
+ "type": "instance",
+ "parent_type": "instances_folder",
+ "parent_id": "node-5.cisco.com-instances",
+ "in_project-Calipso-project": "1",
+ "network_info": [
+ {
+ "network": {
+ "id": "7e59b726-d6f4-451a-a574-c67a920ff627"
+ }
+ }
+ ]
+ }
+]
+
+INSTANCE_WITH_NETWORK = {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "network_info": "[{\"network\": {\"id\": \"7e59b726-d6f4-451a-a574-c67a920ff627\"}}]",
+ "project": "Calipso-project",
+}
+
+INSTANCE_WITH_NETWORK_RESULT = {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "network": ["7e59b726-d6f4-451a-a574-c67a920ff627"],
+ "type": "instance",
+ "parent_type": "instances_folder",
+ "parent_id": "node-5.cisco.com-instances",
+ "in_project-Calipso-project": "1",
+ "network_info": [
+ {
+ "network": {
+ "id": "7e59b726-d6f4-451a-a574-c67a920ff627"
+ }
+ }
+ ]
+}
+
+INSTANCE_WITHOUT_NETWORK = {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "network_info": "[]",
+ "project": "Calipso-project",
+}
+
+INSTANCE_WITHOUT_NETWORK_RESULT = {
+ "host": "node-5.cisco.com",
+ "id": "6f29c867-9150-4533-8e19-70d749b172fa",
+ "network": [],
+ "type": "instance",
+ "parent_type": "instances_folder",
+ "parent_id": "node-5.cisco.com-instances",
+ "in_project-Calipso-project": "1",
+ "network_info": []
+}
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_oteps.py b/app/test/fetch/db_fetch/test_data/db_fetch_oteps.py
new file mode 100644
index 0000000..a5bc63d
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_oteps.py
@@ -0,0 +1,131 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+VEDGE_ID = "3858e121-d861-4348-9d64-a55fcd5bf60a"
+VEDGE = {
+ "configurations": {
+ "tunnel_types": [
+ "vxlan"
+ ],
+ "tunneling_ip": "192.168.2.1"
+ },
+ "host": "node-5.cisco.com",
+ "id": "3858e121-d861-4348-9d64-a55fcd5bf60a",
+ "tunnel_ports": {
+ "vxlan-c0a80203": {
+ },
+ "br-tun": {
+ }
+ },
+ "type": "vedge"
+}
+VEDGE_WITHOUT_CONFIGS ={
+
+}
+VEDGE_WITHOUT_TUNNEL_TYPES = {
+ "configuration": {
+ "tunnel_types": ""
+ }
+}
+NON_ICEHOUSE_CONFIGS = {
+ "distribution": "Mirantis-8.0"
+}
+ICEHOUSE_CONFIGS = {
+ "distribution": "Canonical-icehouse"
+}
+HOST = {
+ "host": "node-5.cisco.com",
+ "id": "node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "name": "node-5.cisco.com"
+}
+OTEPS_WITHOUT_CONFIGURATIONS_IN_VEDGE_RESULTS = []
+OTEPS_WITHOUT_TUNNEL_TYPES_IN_VEDGE_RESULTS = []
+OTEPS_FOR_NON_ICEHOUSE_DISTRIBUTION_RESULTS = [
+ {
+ "host": "node-5.cisco.com",
+ "ip_address": "192.168.2.1",
+ "udp_port": 4789,
+ "id": "node-5.cisco.com-otep",
+ "name": "node-5.cisco.com-otep",
+ "overlay_type": "vxlan",
+ "ports": {
+ "vxlan-c0a80203": {
+ },
+ "br-tun": {
+ }
+ }
+ }
+]
+OTEPS_FOR_ICEHOUSE_DISTRIBUTION_RESULTS = [
+ {
+ "host": "node-5.cisco.com",
+ "ip_address": "192.168.0.4",
+ "id": "node-5.cisco.com-otep",
+ "name": "node-5.cisco.com-otep",
+ "overlay_type": "vxlan",
+ "ports": {
+ "vxlan-c0a80203": {
+ },
+ "br-tun": {
+ }
+ },
+ "udp_port": "67"
+ }
+]
+
+OTEPS = [
+ {
+ "host": "node-5.cisco.com",
+ "ip_address": "192.168.2.1",
+ "udp_port": 4789
+ }
+]
+
+OTEP_FOR_GETTING_VECONNECTOR = {
+ "host": "node-5.cisco.com",
+ "ip_address": "192.168.2.1",
+ "udp_port": 4789,
+ "id": "node-5.cisco.com-otep",
+ "name": "node-5.cisco.com-otep",
+ "overlay_type": "vxlan",
+ "ports": {
+ "vxlan-c0a80203": {
+ },
+ "br-tun": {
+ }
+ }
+}
+HOST_ID = "node-5.cisco.com"
+IFCONFIG_LINES = [
+ "br-mesh Link encap:Ethernet HWaddr 00:50:56:ac:28:9d ",
+ " inet addr:192.168.2.1 Bcast:192.168.2.255 Mask:255.255.255.0",
+ " inet6 addr: fe80::d4e1:8fff:fe33:ed6a/64 Scope:Link",
+ " UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1",
+ " RX packets:2273307 errors:0 dropped:0 overruns:0 frame:0",
+ " TX packets:2255930 errors:0 dropped:0 overruns:0 carrier:0",
+ " collisions:0 txqueuelen:0 ",
+ " RX bytes:578536155 (578.5 MB) TX bytes:598541522 (598.5 MB)",
+ ""
+]
+OTEP_WITH_CONNECTOR = {
+ "host": "node-5.cisco.com",
+ "ip_address": "192.168.2.1",
+ "udp_port": 4789,
+ "id": "node-5.cisco.com-otep",
+ "name": "node-5.cisco.com-otep",
+ "overlay_type": "vxlan",
+ "ports": {
+ "vxlan-c0a80203": {
+ },
+ "br-tun": {
+ }
+ },
+ "vconnector": "br-mesh"
+}
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_vedges_ovs.py b/app/test/fetch/db_fetch/test_data/db_fetch_vedges_ovs.py
new file mode 100644
index 0000000..818704c
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_vedges_ovs.py
@@ -0,0 +1,168 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+VEDGES_FOLDER_ID = "node-6.cisco.com-vedges"
+
+OBJECTS_FROM_DB = [
+ {
+ "host": "node-6.cisco.com",
+ "agent_type": "Open vSwitch agent",
+ "configurations": '{"tunneling_ip": "192.168.2.3"}',
+ }
+]
+
+HOST = {
+ "host": "node-6.cisco.com",
+ "host_type": [
+ "Controller",
+ "Network"
+ ],
+ "id": "node-6.cisco.com",
+ "name": "node-6.cisco.com"
+}
+
+HOST_WITHOUT_REQUIRED_HOST_TYPES = {
+ "id": "node-6.cisco.com",
+ "host_type": []
+}
+
+PORTS = {
+ "ovs-system": {
+ "name": "ovs-system",
+ "id": "0",
+ "internal": True
+ },
+ "qr-bb9b8340-72": {
+ "name": "qr-bb9b8340-72",
+ "id": "1",
+ "internal": True,
+ "tag": "3"
+ },
+ "qr-8733cc5d-b3": {
+ "name": "qr-8733cc5d-b3",
+ "id": "2",
+ "internal": True,
+ "tag": "4"
+ }
+}
+
+TUNNEL_PORTS = {
+ "patch-int": {
+ "interface": "patch-int",
+ "name": "patch-int",
+ "options": {
+ "peer": "patch-tun"
+ },
+ "type": "patch"
+ }
+}
+
+GET_RESULTS = [
+ {
+ 'name': 'node-6.cisco.com-OVS',
+ 'host': 'node-6.cisco.com',
+ 'agent_type': 'Open vSwitch agent',
+ 'configurations': {"tunneling_ip": "192.168.2.3"},
+ 'ports': PORTS,
+ 'tunnel_ports': TUNNEL_PORTS
+ }
+]
+
+
+VSCTL_LINES = [
+ "3b12f08e-4e13-4976-8da5-23314b268805",
+ " Bridge br-int",
+ " fail_mode: secure",
+ " Port \"qr-bb9b8340-72\"",
+ " tag: 3",
+ " Interface \"qr-bb9b8340-72\"",
+ " type: internal",
+ " Port \"qr-8733cc5d-b3\"",
+ " tag: 4",
+ " Interface \"qr-8733cc5d-b3\"",
+ " type: internal",
+ " Bridge br-tun",
+ " fail_mode: secure",
+ " Port patch-int",
+ " Interface patch-int",
+ " type: patch",
+ " options: {peer=patch-tun}",
+]
+
+DPCTL_LINES = [
+ "system@ovs-system:",
+ "\tlookups: hit:14039304 missed:35687906 lost:0",
+ "\tflows: 4",
+ "\tmasks: hit:95173613 total:2 hit/pkt:1.91",
+ "\tport 0: ovs-system (internal)",
+ "\tport 1: qr-bb9b8340-72 (internal)",
+ "\tport 2: qr-8733cc5d-b3 (internal)"
+]
+
+DPCTL_RESULTS = {
+ "ovs-system": {
+ "name": "ovs-system",
+ "id": "0",
+ "internal": True
+ },
+ "qr-bb9b8340-72": {
+ "name": "qr-bb9b8340-72",
+ "id": "1",
+ "internal": True
+ },
+ "qr-8733cc5d-b3": {
+ "name": "qr-8733cc5d-b3",
+ "id": "2",
+ "internal": True
+ }
+}
+
+FETCH__PORT_TAGS_INPUT = {
+ "ovs-system": {
+ "name": "ovs-system",
+ "id": "0",
+ "internal": True
+ },
+ "qr-bb9b8340-72": {
+ "name": "qr-bb9b8340-72",
+ "id": "1",
+ "internal": True
+ },
+ "qr-8733cc5d-b3": {
+ "name": "qr-8733cc5d-b3",
+ "id": "2",
+ "internal": True
+ }
+}
+
+FETCH_PORT_TAGS_RESULT = {
+ "ovs-system": {
+ "name": "ovs-system",
+ "id": "0",
+ "internal": True
+ },
+ "qr-bb9b8340-72": {
+ "name": "qr-bb9b8340-72",
+ "id": "1",
+ "internal": True,
+ "tag": "3"
+ },
+ "qr-8733cc5d-b3": {
+ "name": "qr-8733cc5d-b3",
+ "id": "2",
+ "internal": True,
+ "tag": "4"
+ }
+}
+
+DOC_TO_GET_OVERLAY = {
+ "host": "node-6.cisco.com",
+ "agent_type": "Open vSwitch agent",
+ "configurations": {"tunneling_ip": "192.168.2.3"},
+}
diff --git a/app/test/fetch/db_fetch/test_data/db_fetch_vedges_vpp.py b/app/test/fetch/db_fetch/test_data/db_fetch_vedges_vpp.py
new file mode 100644
index 0000000..24265ae
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_data/db_fetch_vedges_vpp.py
@@ -0,0 +1,89 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+VEDGE_FOLDER_ID = "ubuntu0-vedges"
+
+HOST = {
+ "host_type": [
+ "Controller",
+ "Compute",
+ "Network"
+ ],
+ "id": "ubuntu0",
+}
+
+HOST_WITHOUT_REQUIRED_HOST_TYPE = {
+ "host_type": [
+
+ ]
+}
+
+VERSION = [
+ "vpp v16.09-rc0~157-g203c632 built by localadmin on ubuntu0 at Sun Jun 26 16:35:15 PDT 2016\n"
+]
+
+INTERFACES = [
+ " Name Idx State Counter Count ",
+ "TenGigabitEthernetc/0/0 5 up rx packets 502022",
+ " rx bytes 663436206",
+ " tx packets 81404",
+ " tx bytes 6366378",
+ " drops 1414",
+ " punts 1",
+ " rx-miss 64525",
+ "VirtualEthernet0/0/0 7 up tx packets 31496",
+ " tx bytes 2743185",
+ "local0 0 down ",
+ "pg/stream-0 1 down ",
+]
+
+PORTS = {
+ "TenGigabitEthernetc/0/0": {
+ "id": "5",
+ "name": "TenGigabitEthernetc/0/0",
+ "state": "up"
+ },
+ "VirtualEthernet0/0/0": {
+ "id": "7",
+ "name": "VirtualEthernet0/0/0",
+ "state": "up"
+ },
+ "local0": {
+ "id": "0",
+ "name": "local0",
+ "state": "down"
+ },
+ "pg/stream-0": {
+ "id": "1",
+ "name": "pg/stream-0",
+ "state": "down"
+ }
+}
+
+
+VEDGE_RESULTS = [
+ {
+ "host": "ubuntu0",
+ "id": "ubuntu0-VPP",
+ "name": "VPP-ubuntu0",
+ "agent_type": "VPP",
+ "binary": "vpp v16.09-rc0~157-g203c632",
+ "ports": PORTS
+ }
+]
+
+VEDGE_RESULTS_WITHOUT_BINARY = [
+ {
+ "host": "ubuntu0",
+ "id": "ubuntu0-VPP",
+ "name": "VPP-ubuntu0",
+ "agent_type": "VPP",
+ "ports": PORTS
+ }
+]
diff --git a/app/test/fetch/db_fetch/test_db_access.py b/app/test/fetch/db_fetch/test_db_access.py
new file mode 100644
index 0000000..4ef3e74
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_access.py
@@ -0,0 +1,108 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_access import DbAccess
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_access import *
+from unittest.mock import MagicMock, patch
+from test.fetch.db_fetch.mock_cursor import MockCursor
+
+
+class TestDbAccess(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbAccess()
+
+ @patch("mysql.connector.connect")
+ def test_db_connect(self, db_connect):
+ DbAccess.conn = None
+ db_conn = MagicMock()
+ db_conn.ping = MagicMock()
+ db_connect.return_value = db_conn
+
+ self.fetcher.db_connect(DB_CONFIG['host'], DB_CONFIG['port'],
+ DB_CONFIG['user'], DB_CONFIG['password'],
+ DB_CONFIG['schema'])
+
+ self.assertEqual(True, db_connect.called, "connect method has't been called")
+ db_conn.ping.assert_called_once_with(True)
+
+ def test_connect_to_db(self):
+ DbAccess.conn = None
+ self.fetcher.db_connect = MagicMock()
+ self.fetcher.connect_to_db()
+
+ self.assertEqual(True, self.fetcher.db_connect.called)
+
+ def test_connect_to_db_with_force(self):
+ DbAccess.conn = MagicMock()
+ self.fetcher.db_connect = MagicMock()
+ self.fetcher.connect_to_db(force=True)
+
+ self.assertEqual(True, self.fetcher.db_connect.called)
+
+ def test_connect_to_db_without_force(self):
+ DbAccess.conn = MagicMock()
+ self.fetcher.db_connect = MagicMock()
+ self.fetcher.connect_to_db()
+
+ self.assertEqual(False, self.fetcher.db_connect.called)
+
+ def test_get_objects_list_for_id_with_id(self):
+ # mock the db cursor
+ mock_cursor = MockCursor(OBJECTS_LIST)
+ mock_cursor.execute = MagicMock()
+
+ self.fetcher.connect_to_db = MagicMock()
+ DbAccess.conn.cursor = MagicMock(return_value=mock_cursor)
+
+ result = self.fetcher.get_objects_list_for_id(QUERY_WITH_ID, OBJECT_TYPE, ID)
+
+ mock_cursor.execute.assert_called_once_with(QUERY_WITH_ID, [ID])
+ self.assertEqual(result, OBJECTS_LIST, "Can't get objects list")
+
+ def test_get_objects_list_for_id_without_id(self):
+ mock_cursor = MockCursor(OBJECTS_LIST)
+
+ self.fetcher.connect_to_db = MagicMock()
+ DbAccess.conn.cursor = MagicMock(return_value=mock_cursor)
+ mock_cursor.execute = MagicMock()
+
+ result = self.fetcher.get_objects_list_for_id(QUERY_WITHOUT_ID, OBJECT_TYPE, None)
+
+ mock_cursor.execute.assert_called_once_with(QUERY_WITHOUT_ID)
+ self.assertEqual(result, OBJECTS_LIST, "Can't get objects list")
+
+ def test_get_objects_list_for_id_with_id_with_exception(self):
+ mock_cursor = MockCursor(OBJECTS_LIST)
+ self.fetcher.connect_to_db = MagicMock()
+ # mock exception
+ DbAccess.conn.cursor = MagicMock(return_value=mock_cursor)
+ mock_cursor.execute = MagicMock(side_effect=[AttributeError, ""])
+
+ result = self.fetcher.get_objects_list_for_id(QUERY_WITH_ID, OBJECT_TYPE, ID)
+
+ self.assertEqual(mock_cursor.execute.call_count, 2, "Can't invoke execute method " +
+ "twice when error occurs")
+ self.assertEqual(result, OBJECTS_LIST, "Can't get objects list")
+
+ def test_get_objects_list_for_id_without_id_with_exception(self):
+ mock_cursor = MockCursor(OBJECTS_LIST)
+ self.fetcher.connect_to_db = MagicMock()
+ DbAccess.conn.cursor = MagicMock(return_value=mock_cursor)
+ mock_cursor.execute = MagicMock(side_effect=[AttributeError, ""])
+
+ result = self.fetcher.get_objects_list_for_id(QUERY_WITHOUT_ID,
+ OBJECT_TYPE,
+ None)
+
+ self.assertEqual(mock_cursor.execute.call_count, 2, "Can't invoke execute method " +
+ "twice when error occurs")
+ self.assertEqual(result, OBJECTS_LIST, "Can't get objects list")
diff --git a/app/test/fetch/db_fetch/test_db_fetch_aggregate_hosts.py b/app/test/fetch/db_fetch/test_db_fetch_aggregate_hosts.py
new file mode 100644
index 0000000..2066577
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_fetch_aggregate_hosts.py
@@ -0,0 +1,60 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_fetch_aggregate_hosts import DbFetchAggregateHosts
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_fetch_aggregate_hosts import *
+from unittest.mock import MagicMock
+
+
+class TestDbFetchAggregateHosts(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchAggregateHosts()
+
+ def check_get_results_is_correct(self,
+ objects_list,
+ host_in_inventory,
+ expected_result,
+ err_msg):
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=objects_list)
+ self.inv.get_by_id = MagicMock(return_value=host_in_inventory)
+ result = self.fetcher.get(AGGREGATE["id"])
+
+ self.assertEqual(result, expected_result, err_msg)
+
+ def test_get(self):
+ test_cases = [
+ {
+ "objects_list": HOSTS,
+ "host_in_inventory": HOST_IN_INVENTORY,
+ "expected_result": HOSTS_RESULT,
+ "err_msg": "Can't get correct hosts info"
+ },
+ {
+ "objects_list": [],
+ "host_in_inventory": None,
+ "expected_result": [],
+ "err_msg": "Can't get [] when the "
+ "returned objects list is empty"
+ },
+ {
+ "objects_list": HOSTS,
+ "host_in_inventory": [],
+ "expected_result": HOSTS,
+ "err_msg": "Can't get correct hosts info "
+ "when the host doesn't exist in the inventory"
+ }
+ ]
+ for test_case in test_cases:
+ self.check_get_results_is_correct(test_case["objects_list"],
+ test_case["host_in_inventory"],
+ test_case["expected_result"],
+ test_case["err_msg"])
diff --git a/app/test/fetch/db_fetch/test_db_fetch_aggregates.py b/app/test/fetch/db_fetch/test_db_fetch_aggregates.py
new file mode 100644
index 0000000..12693b7
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_fetch_aggregates.py
@@ -0,0 +1,26 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_fetch_aggregates import DbFetchAggregates
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_fetch_aggregates import *
+from unittest.mock import MagicMock
+
+
+class TestDbFetchAggregates(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchAggregates()
+
+ def test_get(self):
+ self.fetcher.get_objects_list = MagicMock(return_value=OBJECTS_LIST)
+ result = self.fetcher.get(REGION_ID)
+ self.assertEqual(result, OBJECTS_LIST, "Can't get correct " +
+ "aggregates info")
diff --git a/app/test/fetch/db_fetch/test_db_fetch_instances.py b/app/test/fetch/db_fetch/test_db_fetch_instances.py
new file mode 100644
index 0000000..a1207a1
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_fetch_instances.py
@@ -0,0 +1,37 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_fetch_instances import DbFetchInstances
+from test.fetch.test_fetch import TestFetch
+from unittest.mock import MagicMock
+from test.fetch.db_fetch.test_data.db_fetch_instances import *
+
+
+class TestDbFetchInstances(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchInstances()
+
+ def test_get(self):
+ self.fetcher.get_objects_list = MagicMock(return_value=
+ INSTANCES_FROM_DB)
+ self.fetcher.get_instance_data(INSTANCES_FROM_API)
+
+ self.assertEqual(INSTANCES_FROM_API, UPDATED_INSTANCES_DATA)
+
+ def test_build_instance_details_with_network(self):
+ self.fetcher.build_instance_details(INSTANCE_WITH_NETWORK)
+ self.assertEqual(INSTANCE_WITH_NETWORK,
+ INSTANCE_WITH_NETWORK_RESULT)
+
+ def test_build_instance_details_without_network(self):
+ self.fetcher.build_instance_details(INSTANCE_WITHOUT_NETWORK)
+ self.assertEqual(INSTANCE_WITHOUT_NETWORK,
+ INSTANCE_WITHOUT_NETWORK_RESULT)
diff --git a/app/test/fetch/db_fetch/test_db_fetch_oteps.py b/app/test/fetch/db_fetch/test_db_fetch_oteps.py
new file mode 100644
index 0000000..905f55a
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_fetch_oteps.py
@@ -0,0 +1,92 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import copy
+
+from discover.fetchers.db.db_fetch_oteps import DbFetchOteps
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_fetch_oteps import *
+from unittest.mock import MagicMock
+
+
+class TestDbFetchOteps(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchOteps()
+ self.fetcher.set_env(self.env)
+
+ def check_get_oteps_results(self, vedge,
+ config,
+ host,
+ oteps_from_db,
+ expected_results,
+ err_msg):
+ original_get_vconnector = self.fetcher.get_vconnector
+ self.fetcher.get_vconnector = MagicMock()
+ self.fetcher.inv.get_by_id = MagicMock(side_effect=[vedge, host])
+ self.fetcher.config.get_env_config = MagicMock(return_value=config)
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=oteps_from_db)
+ results = self.fetcher.get(VEDGE_ID)
+ self.assertEqual(results, expected_results, err_msg)
+ self.fetcher.get_vconnector = original_get_vconnector
+
+ def test_get(self):
+ test_cases = [
+ {
+ "vedge": VEDGE_WITHOUT_CONFIGS,
+ "config": NON_ICEHOUSE_CONFIGS,
+ "host": None,
+ "oteps_from_db": None,
+ "expected_results": [],
+ "err_msg": "Can't get [] when the vedge " +
+ "doesn't contains configurations"
+ },
+ {
+ "vedge": VEDGE_WITHOUT_TUNNEL_TYPES,
+ "config": NON_ICEHOUSE_CONFIGS,
+ "host": None,
+ "oteps_from_db": None,
+ "expected_results": [],
+ "err_msg": "Can't get [] when the vedge configurations " +
+ "doesn't contain tunnel_types"
+ },
+ {
+ "vedge": VEDGE,
+ "config": ICEHOUSE_CONFIGS,
+ "host": HOST,
+ "oteps_from_db": None,
+ "expected_results": OTEPS_FOR_ICEHOUSE_DISTRIBUTION_RESULTS,
+ "err_msg": "Can't get correct oteps result " +
+ "when the distribution is icehouse"
+ },
+ {
+ "vedge": VEDGE,
+ "config": NON_ICEHOUSE_CONFIGS,
+ "host": None,
+ "oteps_from_db": OTEPS,
+ "expected_results": OTEPS_FOR_NON_ICEHOUSE_DISTRIBUTION_RESULTS,
+ "err_msg": "Can't get correct oteps result " +
+ "when the distribution is not icehouse"
+ }
+ ]
+ for test_case in test_cases:
+ self.check_get_oteps_results(test_case["vedge"],
+ test_case["config"],
+ test_case["host"],
+ test_case["oteps_from_db"],
+ test_case["expected_results"],
+ test_case["err_msg"])
+
+ def test_get_vconnectors(self):
+ self.fetcher.run_fetch_lines = MagicMock(return_value=IFCONFIG_LINES)
+ self.fetcher.get_vconnector(OTEP_FOR_GETTING_VECONNECTOR,
+ HOST_ID, VEDGE)
+ self.assertEqual(OTEP_FOR_GETTING_VECONNECTOR, OTEP_WITH_CONNECTOR,
+ "Can't get vconnector from the config lines for otep")
diff --git a/app/test/fetch/db_fetch/test_db_fetch_vedges_ovs.py b/app/test/fetch/db_fetch/test_db_fetch_vedges_ovs.py
new file mode 100644
index 0000000..b08aebd
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_fetch_vedges_ovs.py
@@ -0,0 +1,109 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_fetch_vedges_ovs import DbFetchVedgesOvs
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_fetch_vedges_ovs import *
+from unittest.mock import MagicMock
+
+
+class TestDbFetchVedgesOvs(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchVedgesOvs()
+ self.fetcher.set_env(self.env)
+
+ def check_get_result(self,
+ objects_from_db, host,
+ vsctl_lines, ports, tunnel_ports,
+ expected_result, err_msg):
+ # store original methods
+ original_get_objects_list_by_id = self.fetcher.get_objects_list_for_id
+ original_get_by_id = self.fetcher.inv.get_by_id
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_fetch_ports = self.fetcher.fetch_ports
+ original_get_overlay_tunnels = self.fetcher.get_overlay_tunnels
+
+ self.fetcher.get_objects_list_for_id = MagicMock(return_value=objects_from_db)
+ self.fetcher.inv.get_by_id = MagicMock(return_value=host)
+ self.fetcher.run_fetch_lines = MagicMock(return_value=vsctl_lines)
+ self.fetcher.fetch_ports = MagicMock(return_value=ports)
+ self.fetcher.get_overlay_tunnels = MagicMock(return_value=tunnel_ports)
+
+ results = self.fetcher.get(VEDGES_FOLDER_ID)
+ self.assertEqual(results, expected_result, err_msg)
+
+ # restore methods
+ self.fetcher.get_objects_list_for_id = original_get_objects_list_by_id
+ self.fetcher.inv.get_by_id = original_get_by_id
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.fetch_ports = original_fetch_ports
+ self.fetcher.get_overlay_tunnels = original_get_overlay_tunnels
+
+ def test_get(self):
+ test_cases = [
+ {
+ "objects_from_db": OBJECTS_FROM_DB,
+ "host": HOST,
+ "vsctl_lines": "",
+ "ports": PORTS,
+ "tunnel_ports": TUNNEL_PORTS,
+ "expected_result": GET_RESULTS,
+ "err_msg": "Can't get correct vedges"
+ },
+ {
+ "objects_from_db": OBJECTS_FROM_DB,
+ "host": [],
+ "vsctl_lines": "",
+ "ports": {},
+ "tunnel_ports": [],
+ "expected_result": [],
+ "err_msg": "Can't get [] when the host " +
+ "doesn't exist"
+ },
+ {
+ "objects_from_db": OBJECTS_FROM_DB,
+ "host": HOST_WITHOUT_REQUIRED_HOST_TYPES,
+ "vsctl_lines": "",
+ "ports": {},
+ "tunnel_ports": [],
+ "expected_result": [],
+ "err_msg": "Can't get [] when the host " +
+ "doesn't have required host types"
+ }
+ ]
+ for test_case in test_cases:
+ self.check_get_result(test_case["objects_from_db"],
+ test_case["host"],
+ test_case["vsctl_lines"],
+ test_case["ports"],
+ test_case["tunnel_ports"],
+ test_case["expected_result"],
+ test_case["err_msg"])
+
+ def test_fetch_ports_from_dpctl(self):
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ self.fetcher.run_fetch_lines = MagicMock(return_value=DPCTL_LINES)
+
+ results = self.fetcher.fetch_ports_from_dpctl(HOST['id'])
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.assertEqual(results, DPCTL_RESULTS,
+ "Can' t get correct ports info from dpctl lines")
+
+ def test_fetch_port_tags_from_vsctl(self):
+ ports = self.fetcher.fetch_port_tags_from_vsctl(VSCTL_LINES,
+ FETCH__PORT_TAGS_INPUT)
+ self.assertEqual(ports, FETCH_PORT_TAGS_RESULT,
+ "Can't fetch tag from vsctl")
+
+ def test_get_overlay_tunnels(self):
+ results = self.fetcher.get_overlay_tunnels(DOC_TO_GET_OVERLAY,
+ VSCTL_LINES)
+ self.assertEqual(results, TUNNEL_PORTS)
diff --git a/app/test/fetch/db_fetch/test_db_fetch_vedges_vpp.py b/app/test/fetch/db_fetch/test_db_fetch_vedges_vpp.py
new file mode 100644
index 0000000..9e6f497
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_db_fetch_vedges_vpp.py
@@ -0,0 +1,82 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_fetch_vedges_vpp import DbFetchVedgesVpp
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_fetch_vedges_vpp import *
+from unittest.mock import MagicMock
+
+
+class TestDbFetchVedgesVpp(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchVedgesVpp()
+ self.fetcher.set_env(self.env)
+
+ def check_get_results(self, version,
+ interfaces, host,
+ expected_results, err_msg):
+ original_run_fetch_lines = self.fetcher.run_fetch_lines
+ original_get_by_id = self.fetcher.inv.get_by_id
+
+ self.fetcher.run_fetch_lines = MagicMock(side_effect=[version, interfaces])
+ self.fetcher.inv.get_by_id = MagicMock(return_value=host)
+
+ vedges = self.fetcher.get(VEDGE_FOLDER_ID)
+ self.assertEqual(vedges, expected_results, err_msg)
+
+ self.fetcher.run_fetch_lines = original_run_fetch_lines
+ self.fetcher.inv.get_by_id = original_get_by_id
+
+ def test_get(self):
+ test_cases = [
+ {
+ "version": VERSION,
+ "interfaces": INTERFACES,
+ "host": HOST,
+ "expected_results": VEDGE_RESULTS,
+ "err_msg": "Can' get correct vedges"
+ },
+ {
+ "version": [],
+ "interfaces": INTERFACES,
+ "host": HOST,
+ "expected_results": VEDGE_RESULTS_WITHOUT_BINARY,
+ "err_msg": "Can' get correct vedges when " +
+ "it can't get version info host"
+ },
+ {
+ "version": VERSION,
+ "interfaces": INTERFACES,
+ "host": [],
+ "expected_results": [],
+ "err_msg": "Can't get [] when the host of the " +
+ "vedge doesn't exist in db"
+ },
+ {
+ "version": VERSION,
+ "interfaces": INTERFACES,
+ "host": HOST_WITHOUT_REQUIRED_HOST_TYPE,
+ "expected_results": [],
+ "err_msg": "Can't get [] when the host of the " +
+ "vedge doesn't contains required host types"
+ }
+ ]
+
+ for test_case in test_cases:
+ self.check_get_results(test_case["version"],
+ test_case["interfaces"],
+ test_case["host"],
+ test_case["expected_results"],
+ test_case["err_msg"])
+
+ def test_fetch_ports(self):
+ ports = self.fetcher.fetch_ports(INTERFACES)
+ self.assertEqual(ports, PORTS, "Can't get the correct ports info") \ No newline at end of file
diff --git a/app/test/fetch/db_fetch/test_fetch_host_network_agents.py b/app/test/fetch/db_fetch/test_fetch_host_network_agents.py
new file mode 100644
index 0000000..fd68a56
--- /dev/null
+++ b/app/test/fetch/db_fetch/test_fetch_host_network_agents.py
@@ -0,0 +1,66 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import copy
+
+from discover.fetchers.db.db_fetch_host_network_agents import DbFetchHostNetworkAgents
+from test.fetch.test_fetch import TestFetch
+from test.fetch.db_fetch.test_data.db_fetch_host_network_agents import *
+from unittest.mock import MagicMock
+
+
+class TestFetchHostNetworkAgents(TestFetch):
+
+ def setUp(self):
+ self.configure_environment()
+ self.fetcher = DbFetchHostNetworkAgents()
+
+ def check_get_result(self,
+ config,
+ network_agent_res,
+ expected_result,
+ err_msg):
+ self.fetcher.env_config = config
+ self.fetcher.get_objects_list_for_id =\
+ MagicMock(return_value=network_agent_res)
+ result = self.fetcher.get(NETWORK_AGENT_FOLDER_ID)
+ self.assertEqual(result, expected_result, err_msg)
+
+ def test_get(self):
+ test_cases = [
+ {
+ 'config': CONFIG_WITH_MECHANISM_DRIVERS,
+ 'network_agent_res': copy.deepcopy(NETWORK_AGENT),
+ 'expected_result':
+ NETWORK_AGENT_WITH_MECHANISM_DRIVERS_IN_CONFIG_RESULTS,
+ 'err_msg': "Can't get correct result when the " +
+ "mechanism drivers exists in the config"
+ },
+ {
+ 'config': CONFIG_WITHOUT_MECHANISM_DRIVERS,
+ 'network_agent_res': copy.deepcopy(NETWORK_AGENT),
+ 'expected_result':
+ NETWORK_AGENT_WITHOUT_MECHANISM_DRIVERS_IN_CONFIG_RESULTS,
+ 'err_msg': "Can't get correct result when the " +
+ "mechanism drivers doesn't exist in the config"
+ },
+ {
+ 'config': CONFIG_WITH_MECHANISM_DRIVERS,
+ 'network_agent_res': [],
+ 'expected_result': [],
+ 'err_msg': "Can't get [] when the network agent result " +
+ "is empty"
+ }
+ ]
+
+ for test_case in test_cases:
+ self.check_get_result(test_case['config'],
+ test_case['network_agent_res'],
+ test_case['expected_result'],
+ test_case['err_msg'])
diff --git a/app/test/fetch/test_fetch.py b/app/test/fetch/test_fetch.py
new file mode 100644
index 0000000..b9fd3f1
--- /dev/null
+++ b/app/test/fetch/test_fetch.py
@@ -0,0 +1,46 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import unittest
+
+from discover.configuration import Configuration
+from discover.fetchers.db.db_access import DbAccess
+from test.fetch.config.test_config import MONGODB_CONFIG, ENV_CONFIG, COLLECTION_CONFIG
+from test.fetch.api_fetch.test_data.regions import REGIONS
+from test.fetch.api_fetch.test_data.configurations import CONFIGURATIONS
+from unittest.mock import MagicMock
+from utils.inventory_mgr import InventoryMgr
+from utils.mongo_access import MongoAccess
+from utils.ssh_connection import SshConnection
+from utils.ssh_conn import SshConn
+
+
+class TestFetch(unittest.TestCase):
+
+ def configure_environment(self):
+ self.env = ENV_CONFIG
+ self.inventory_collection = COLLECTION_CONFIG
+ # mock the Mongo Access
+ MongoAccess.mongo_connect = MagicMock()
+ MongoAccess.db = MagicMock()
+
+ self.conf = Configuration()
+ self.conf.use_env = MagicMock()
+ self.conf.environment = CONFIGURATIONS
+ self.conf.configuration = CONFIGURATIONS["configuration"]
+
+ self.inv = InventoryMgr()
+ self.inv.set_collections(self.inventory_collection)
+ DbAccess.conn = MagicMock()
+ SshConnection.connect = MagicMock()
+ SshConnection.check_definitions = MagicMock()
+ SshConn.check_definitions = MagicMock()
+
+ def set_regions_for_fetcher(self, fetcher):
+ fetcher.regions = REGIONS
diff --git a/app/test/scan/__init__.py b/app/test/scan/__init__.py
new file mode 100644
index 0000000..1e85a2a
--- /dev/null
+++ b/app/test/scan/__init__.py
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+
diff --git a/app/test/scan/config/__init__.py b/app/test/scan/config/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/scan/config/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/scan/config/test_config.py b/app/test/scan/config/test_config.py
new file mode 100644
index 0000000..176fd48
--- /dev/null
+++ b/app/test/scan/config/test_config.py
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+# local config info for test.
+
+
+MONGODB_CONFIG = 'your-mongo-config-path-here'
+
+ENV_CONFIG = 'your-env-name-here'
+
+COLLECTION_CONFIG = 'your-inventory-collection-name-here'
diff --git a/app/test/scan/main.py b/app/test/scan/main.py
new file mode 100644
index 0000000..fb8c4b5
--- /dev/null
+++ b/app/test/scan/main.py
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import unittest
+
+from test.scan.test_scanner import TestScanner
+from test.scan.test_scan_controller import TestScanController
+from test.scan.test_scan_metadata_parser import TestScanMetadataParser
+
+if __name__=='__main__':
+ unittest.main()
diff --git a/app/test/scan/mock_module.py b/app/test/scan/mock_module.py
new file mode 100644
index 0000000..e7aeb13
--- /dev/null
+++ b/app/test/scan/mock_module.py
@@ -0,0 +1,37 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+class ScanEnvironment:
+
+ run_scan_count = 0
+ scan_links_count = 0
+ scan_cliques_count = 0
+ result = []
+
+ def set_result(self, result):
+ self.result = result
+
+ def run_scan(self, *args):
+ ScanEnvironment.run_scan_count += 1
+ return self.result
+
+ def scan_links(self, *args):
+ ScanEnvironment.scan_links_count += 1
+
+ def scan_cliques(self, *args):
+ ScanEnvironment.scan_cliques_count += 1
+
+ def set_env(self, env):
+ pass
+
+ @classmethod
+ def reset_counts(cls):
+ cls.run_scan_count = 0
+ cls.scan_cliques_count = 0
+ cls.scan_links_count = 0 \ No newline at end of file
diff --git a/app/test/scan/test_data/__init__.py b/app/test/scan/test_data/__init__.py
new file mode 100644
index 0000000..b0637e9
--- /dev/null
+++ b/app/test/scan/test_data/__init__.py
@@ -0,0 +1,9 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
diff --git a/app/test/scan/test_data/configurations.py b/app/test/scan/test_data/configurations.py
new file mode 100644
index 0000000..da68dd1
--- /dev/null
+++ b/app/test/scan/test_data/configurations.py
@@ -0,0 +1,69 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+CONFIGURATIONS = {
+ "app_path": "/home/scan/calipso_prod/app/",
+ "scanners_file": "/home/yarony/osdna_dev/app/discover/scanners.json",
+ "configuration": [
+ {
+ "mock": "True",
+ "host": "10.56.20.239",
+ "name": "mysql",
+ "password": "102QreDdiD5sKcvNf9qbHrmr",
+ "port": 3307.0,
+ "user": "root",
+ "schema": "nova"
+ },
+ {
+ "name": "OpenStack",
+ "host": "10.56.20.239",
+ "admin_token": "38MUh19YWcgQQUlk2VEFQ7Ec",
+ "port": "5000",
+ "user": "admin",
+ "pwd": "admin"
+ },
+ {
+ "host": "10.56.20.239",
+ "key": "/Users/ngrandhi/.ssh/id_rsa",
+ "name": "CLI",
+ "pwd": "",
+ "user": "root"
+ },
+ {
+ "name": "AMQP",
+ "host": "10.56.20.239",
+ "port": "5673",
+ "user": "nova",
+ "password": "NF2nSv3SisooxPkCTr8fbfOa"
+ },
+ {
+ "config_folder": "/tmp/sensu_config",
+ "provision": "Deploy",
+ "env_type": "development",
+ "name": "Monitoring",
+ "rabbitmq_port": "5672",
+ "rabbitmq_pass": "osdna",
+ "rabbitmq_user": "sensu",
+ "ssh_port": "20022",
+ "ssh_user": "scan",
+ "ssh_password": "scan",
+ "server_ip": "korlev-osdna-staging1.cisco.com",
+ "server_name": "osdna-sensu",
+ "type": "Sensu"
+ }
+ ],
+ "distribution": "Mirantis-8.0",
+ "last_scanned:": "5/8/16",
+ "name": "Mirantis-Liberty-Nvn",
+ "mechanism_drivers": [
+ "OVS"
+ ],
+ "operational": "yes",
+ "type": "environment"
+}
diff --git a/app/test/scan/test_data/metadata.py b/app/test/scan/test_data/metadata.py
new file mode 100644
index 0000000..ed47c80
--- /dev/null
+++ b/app/test/scan/test_data/metadata.py
@@ -0,0 +1,318 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+METADATA_EMPTY = {}
+
+METADATA_SCANNERS_MISSING = {"scanners_package": "discover.fetchers"}
+
+METADATA_NO_PACKAGE = {
+ "scanners": {}
+}
+
+METADATA_NO_SCANNERS = {
+ "scanners_package": "discover.fetchers"
+}
+
+METADATA_ZERO_SCANNERS = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {}
+}
+
+METADATA_SIMPLE_SCANNER = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregate": [
+ {
+ "type": "host_ref",
+ "fetcher": "DbFetchAggregateHosts"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_UNKNOWN_ATTRIBUTE = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregate": [
+ {
+ "xyz": "123",
+ "type": "host_ref",
+ "fetcher": "DbFetchAggregateHosts"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_NO_TYPE = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregate": [
+ {
+ "fetcher": "DbFetchAggregateHosts"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_NO_FETCHER = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregate": [
+ {
+ "type": "host_ref"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_INCORRECT_TYPE = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregate": [
+ {
+ "type": "t1",
+ "fetcher": "DbFetchAggregateHosts"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_INCORRECT_FETCHER = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregate": [
+ {
+ "type": "host_ref",
+ "fetcher": "f1"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_CHILD = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregatesRoot": [
+ {
+ "type": "aggregate",
+ "fetcher": "DbFetchAggregates",
+ "children_scanner": "ScanAggregate"
+ }
+ ],
+ "ScanAggregate": [
+ {
+ "type": "host_ref",
+ "fetcher": "DbFetchAggregateHosts"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_INCORRECT_CHILD = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregatesRoot": [
+ {
+ "type": "aggregate",
+ "fetcher": "DbFetchAggregates",
+ "children_scanner": 1
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_MISSING_CHILD = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanAggregatesRoot": [
+ {
+ "type": "aggregate",
+ "fetcher": "DbFetchAggregates",
+ "children_scanner": "ScanAggregate"
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_FETCHER_INVALID_DICT = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanEnvironment": [
+ {
+ "type": "regions_folder",
+ "fetcher": {
+ "types_name": "regions",
+ "parent_type": "environment"
+ }
+ },
+ ]
+
+ }
+}
+
+METADATA_SCANNER_WITH_FOLDER = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanEnvironment": [
+ {
+ "type": "regions_folder",
+ "fetcher": {
+ "folder": 1,
+ "types_name": "regions",
+ "parent_type": "environment"
+ }
+ },
+ {
+ "type": "projects_folder",
+ "fetcher": {
+ "folder": 1,
+ "types_name": "projects",
+ "parent_type": "environment"
+ }
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_INVALID_CONDITION = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanHost": [
+ {
+ "type": "pnics_folder",
+ "fetcher": "DbFetchAggregateHosts",
+ "environment_condition": 1
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_INVALID_MECHANISM_DRIVER_CONDITION = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanHost": [
+ {
+ "type": "pnics_folder",
+ "fetcher": {
+ "folder": 1,
+ "types_name": "pnics",
+ "parent_type": "host",
+ "text": "pNICs"
+ },
+ "environment_condition": {
+ "mechanism_drivers": ""
+ }
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_INVALID_MECHANISM_DRIVER = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanHost": [
+ {
+ "type": "pnics_folder",
+ "fetcher": {
+ "folder": 1,
+ "types_name": "pnics",
+ "parent_type": "host",
+ "text": "pNICs"
+ },
+ "environment_condition": {
+ "mechanism_drivers": [ 1, 2]
+ }
+ }
+ ]
+ }
+}
+
+METADATA_SCANNER_WITH_CONDITION = {
+ "scanners_package": "discover.fetchers",
+ "scanners": {
+ "ScanHost": [
+ {
+ "type": "pnics_folder",
+ "fetcher": {
+ "folder": 1,
+ "types_name": "pnics",
+ "parent_type": "host",
+ "text": "pNICs"
+ },
+ "environment_condition": {
+ "mechanism_drivers": [
+ "OVS",
+ "LXB"
+ ]
+ }
+ }
+ ]
+ }
+}
+
+CONSTANTS = {
+ "scan_object_types": {
+ "name": "scan_object_types",
+ "data": [
+ {
+ "value": "regions_folder",
+ "label": "regions_folder"
+ },
+ {
+ "value": "pnics_folder",
+ "label": "pnics_folder"
+ },
+ {
+ "value": "projects_folder",
+ "label": "projects_folder"
+ },
+ {
+ "value": "aggregate",
+ "label": "aggregate"
+ },
+ {
+ "value": "host",
+ "label": "host"
+ },
+ {
+ "value": "region",
+ "label": "region"
+ },
+ {
+ "value": "host_ref",
+ "label": "host_ref"
+ }
+ ]
+ },
+ "mechanism_drivers": {
+ "data": [
+ {
+ "label": "OVS",
+ "value": "OVS"
+ },
+ {
+ "label": "VPP",
+ "value": "VPP"
+ },
+ {
+ "label": "LXB",
+ "value": "LXB"
+ },
+ {
+ "label": "Arista",
+ "value": "Arista"
+ },
+ {
+ "label": "Nexus",
+ "value": "Nexus"
+ }
+ ],
+ "name": "mechanism_drivers"
+ }
+}
diff --git a/app/test/scan/test_data/scan.py b/app/test/scan/test_data/scan.py
new file mode 100644
index 0000000..fa36c3e
--- /dev/null
+++ b/app/test/scan/test_data/scan.py
@@ -0,0 +1,435 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+UNIT_TESTS_ENV = "WebEX-Mirantis@Cisco"
+UNIT_TESTS_INVENTORY = 'unit_tests'
+
+MONGO_CONFIG = 'mongo_config_file.txt'
+
+DEFAULT_ARGUMENTS = {
+ "MONGO_CONFIG": "",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "environment",
+ "INVENTORY": "inventory",
+ "SCAN_SELF": False,
+ "ID": UNIT_TESTS_ENV,
+ "PARENT_ID": "",
+ "PARENT_TYPE": "",
+ "ID_FIELD": "id",
+ "LOGLEVEL": "INFO",
+ "INVENTORY_ONLY": False,
+ "LINKS_ONLY": False,
+ "CLIQUES_ONLY": False,
+ "CLEAR": False
+}
+
+SHORT_FLAGS_ARGUMENTS = {
+ "MONGO_CONFIG": "mongo_config_file",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "project",
+ "INVENTORY": UNIT_TESTS_INVENTORY,
+ "SCAN_SELF": True,
+ "ID": "admin",
+ "PARENT_ID": "RegionOne",
+ "PARENT_TYPE": "Region",
+ "ID_FIELD": "name",
+ "LOGLEVEL": "ERROR"
+}
+
+ARGUMENTS_FULL = {
+ "MONGO_CONFIG": "mongo_config_file",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "project",
+ "INVENTORY": UNIT_TESTS_INVENTORY,
+ "SCAN_SELF": True,
+ "ID": "admin",
+ "PARENT_ID": "RegionOne",
+ "PARENT_TYPE": "Region",
+ "ID_FIELD": "name",
+ "LOGLEVEL": "ERROR",
+ "INVENTORY_ONLY": False,
+ "LINKS_ONLY": False,
+ "CLIQUES_ONLY": False,
+ "CLEAR": True,
+ "CLEAR_ALL": False
+}
+
+ARGUMENTS_FULL_CLEAR_ALL = {
+ "MONGO_CONFIG": "mongo_config_file",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "project",
+ "INVENTORY": UNIT_TESTS_INVENTORY,
+ "SCAN_SELF": True,
+ "ID": "admin",
+ "PARENT_ID": "RegionOne",
+ "PARENT_TYPE": "Region",
+ "ID_FIELD": "name",
+ "LOGLEVEL": "ERROR",
+ "INVENTORY_ONLY": False,
+ "LINKS_ONLY": False,
+ "CLIQUES_ONLY": False,
+ "CLEAR": False,
+ "CLEAR_ALL": True
+}
+
+ARGUMENTS_FULL_INVENTORY_ONLY = {
+ "MONGO_CONFIG": "mongo_config_file",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "project",
+ "INVENTORY": UNIT_TESTS_INVENTORY,
+ "SCAN_SELF": True,
+ "ID": "admin",
+ "PARENT_ID": "RegionOne",
+ "PARENT_TYPE": "Region",
+ "ID_FIELD": "name",
+ "LOGLEVEL": "ERROR",
+ "INVENTORY_ONLY": True,
+ "LINKS_ONLY": False,
+ "CLIQUES_ONLY": False,
+ "CLEAR": True,
+ "CLEAR_ALL": False
+}
+
+ARGUMENTS_FULL_LINKS_ONLY = {
+ "MONGO_CONFIG": "mongo_config_file",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "project",
+ "INVENTORY": UNIT_TESTS_INVENTORY,
+ "SCAN_SELF": True,
+ "ID": "admin",
+ "PARENT_ID": "RegionOne",
+ "PARENT_TYPE": "Region",
+ "ID_FIELD": "name",
+ "LOGLEVEL": "ERROR",
+ "INVENTORY_ONLY": False,
+ "LINKS_ONLY": True,
+ "CLIQUES_ONLY": False,
+ "CLEAR": True,
+ "CLEAR_ALL": False
+}
+
+ARGUMENTS_FULL_CLIQUES_ONLY = {
+ "MONGO_CONFIG": "mongo_config_file",
+ "ENV": UNIT_TESTS_ENV,
+ "TYPE": "project",
+ "INVENTORY": UNIT_TESTS_INVENTORY,
+ "SCAN_SELF": True,
+ "ID": "admin",
+ "PARENT_ID": "RegionOne",
+ "PARENT_TYPE": "Region",
+ "ID_FIELD": "name",
+ "LOGLEVEL": "ERROR",
+ "INVENTORY_ONLY": False,
+ "LINKS_ONLY": False,
+ "CLIQUES_ONLY": True,
+ "CLEAR": True,
+ "CLEAR_ALL": False
+}
+
+FORM = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": False,
+ "cliques_only": False,
+ "clear": True,
+ "type": "region",
+ "env": UNIT_TESTS_ENV,
+ "id": "RegionOne",
+ "parent_id": UNIT_TESTS_ENV + "-regions",
+ "parent_type": "regions_folder",
+ "id_field": "id",
+ "scan_self": False,
+ "child_type": "region",
+ "child_id": None
+}
+
+
+SCAN_ENV_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": False,
+ "cliques_only": False,
+ "clear": True,
+ "object_type": "environment",
+ "env": UNIT_TESTS_ENV,
+ "id": "",
+ "parent_id": "",
+ "type_to_scan": "",
+ "id_field": "id",
+ "scan_self": False,
+ "child_type": "environment",
+ "child_id": None
+}
+
+SCAN_ENV_INVENTORY_ONLY_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": True,
+ "links_only": False,
+ "cliques_only": False,
+ "clear": True,
+ "object_type": "environment",
+ "env": UNIT_TESTS_ENV,
+ "id": '',
+ "parent_id": "",
+ "type_to_scan": "",
+ "id_field": "id",
+ "scan_self": False,
+ "child_type": "environment",
+ "child_id": None
+}
+
+SCAN_ENV_LINKS_ONLY_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": True,
+ "cliques_only": False,
+ "clear": True,
+ "object_type": "environment",
+ "env": UNIT_TESTS_ENV,
+ "id": '',
+ "parent_id": "",
+ "type_to_scan": "",
+ "id_field": "id",
+ "scan_self": False,
+ "child_type": "environment",
+ "child_id": None
+}
+
+SCAN_ENV_CLIQUES_ONLY_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": False,
+ "cliques_only": True,
+ "clear": True,
+ "object_type": "environment",
+ "env": UNIT_TESTS_ENV,
+ "id": '',
+ "parent_id": "",
+ "type_to_scan": "",
+ "id_field": "id",
+ "scan_self": False,
+ "child_type": "environment",
+ "child_id": None
+}
+
+PREPARED_ENV_PLAN = {
+ 'obj': {
+ 'id': UNIT_TESTS_ENV
+ },
+ 'child_id': None,
+ 'environment': UNIT_TESTS_ENV,
+ 'inventory_only': False,
+ 'clear': True,
+ 'links_only': False,
+ 'scanner_class': 'ScanEnvironment',
+ 'object_type': 'environment',
+ 'id': UNIT_TESTS_ENV,
+ 'inventory': UNIT_TESTS_INVENTORY,
+ 'loglevel': 'INFO',
+ 'child_type': None,
+ 'type_to_scan': '',
+ 'cliques_only': False,
+ 'id_field': 'id',
+ 'parent_id': '',
+ 'scan_self': False,
+ 'env': UNIT_TESTS_ENV
+}
+
+SCANNER_CLASS = "ScanEnvironment"
+SCANNER_TYPE_FOR_ENV = "ScanEnvironment"
+OBJ_ID_FOR_ENV = ""
+CHILD_TYPE_FOR_ENV = None
+CHILD_ID_FOR_ENV = None
+
+PREPARED_ENV_INVENTORY_ONLY_PLAN = {
+ 'obj': {
+ 'id': UNIT_TESTS_ENV
+ },
+ 'child_id': None,
+ 'clear': True,
+ 'inventory_only': True,
+ 'links_only': False,
+ 'scanner_class': 'ScanEnvironment',
+ 'object_type': 'environment',
+ 'id': UNIT_TESTS_ENV,
+ 'inventory': UNIT_TESTS_INVENTORY,
+ 'loglevel': 'INFO',
+ 'child_type': None,
+ 'type_to_scan': '',
+ 'cliques_only': False,
+ 'id_field': 'id',
+ 'parent_id': '',
+ 'scan_self': False,
+ 'env': UNIT_TESTS_ENV
+}
+
+PREPARED_ENV_LINKS_ONLY_PLAN = {
+ 'obj': {
+ 'id': UNIT_TESTS_ENV
+ },
+ 'child_id': None,
+ 'clear': True,
+ 'inventory_only': False,
+ 'links_only': True,
+ 'cliques_only': False,
+ 'scanner_class': 'ScanEnvironment',
+ 'object_type': 'environment',
+ 'id': UNIT_TESTS_ENV,
+ 'inventory': UNIT_TESTS_INVENTORY,
+ 'loglevel': 'INFO',
+ 'child_type': None,
+ 'type_to_scan': '',
+ 'id_field': 'id',
+ 'parent_id': '',
+ 'scan_self': False,
+ 'env': UNIT_TESTS_ENV
+}
+
+PREPARED_ENV_CLIQUES_ONLY_PLAN = {
+ 'obj': {
+ 'id': UNIT_TESTS_ENV
+ },
+ 'child_id': None,
+ 'clear': True,
+ 'inventory_only': False,
+ 'links_only': False,
+ 'cliques_only': True,
+ 'scanner_class': 'ScanEnvironment',
+ 'object_type': 'environment',
+ 'id': UNIT_TESTS_ENV,
+ 'inventory': UNIT_TESTS_INVENTORY,
+ 'loglevel': 'INFO',
+ 'child_type': None,
+ 'type_to_scan': '',
+ 'id_field': 'id',
+ 'parent_id': '',
+ 'scan_self': False,
+ 'env': UNIT_TESTS_ENV
+}
+
+SCAN_REGION_FOLDER_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": False,
+ "cliques_only": False,
+ "clear": True,
+ "object_type": "regions_folder",
+ "env": UNIT_TESTS_ENV,
+ "id": UNIT_TESTS_ENV + "-regions",
+ "parent_id": UNIT_TESTS_ENV,
+ "parent_type": "environment",
+ "type_to_scan": "regions_folder",
+ "id_field": "id",
+ "scan_self": False,
+ "type": "regions_folder"
+}
+
+SCAN_REGION_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": False,
+ "cliques_only": False,
+ "clear": True,
+ "object_type": "region",
+ "env": UNIT_TESTS_ENV,
+ "id": "RegionOne",
+ "parent_id": UNIT_TESTS_ENV + "-regions",
+ "parent_type": "regions_folder",
+ "type_to_scan": "region",
+ "id_field": "id",
+ "scan_self": False,
+ "type": "region",
+}
+
+SCANNER_TYPE_FOR_REGION = "ScanRegionsRoot"
+OBJ_ID_FOR_REGION = UNIT_TESTS_ENV + "-regions"
+CHILD_TYPE_FOR_REGION = "region"
+CHILD_ID_FOR_REGION = "RegionOne"
+
+REGIONS_FOLDER = {
+ "id": OBJ_ID_FOR_REGION,
+ "type": "regions_folder",
+ "parent_type": "environment",
+ "object_name": "Regions",
+ "parent_id": UNIT_TESTS_ENV,
+ "name": "Regions",
+ "create_object": True,
+ "text": "Regions"
+}
+
+SCAN_PROJECT_FOLDER_PLAN_TO_BE_PREPARED = {
+ "loglevel": "INFO",
+ "inventory_only": False,
+ "links_only": False,
+ "cliques_only": False,
+ "clear": True,
+ "object_type": "projects_folder",
+ "env": UNIT_TESTS_ENV,
+ "object_id": UNIT_TESTS_ENV + "-projects",
+ "parent_id": UNIT_TESTS_ENV,
+ "type_to_scan": "project",
+ "id_field": "id",
+ "scan_self": False,
+ "child_type": "regions_folder",
+ "child_id": None
+}
+
+SCANNER_CLASS_FOR_REGION_FOLDER = "ScanEnvironment"
+OBJ_ID_FOR_REGION_FOLDER = UNIT_TESTS_ENV
+CHILD_TYPE_FOR_REGION_FOLDER = "regions_folder"
+CHILD_ID_FOR_REGION_FOLDER = UNIT_TESTS_ENV + "-regions"
+
+DEFAULT_COMMAND_ARGS = ["scanner.py"]
+
+SHORT_COMMAND_ARGS = ["scanner.py", "-m", "mongo_config_file",
+ "-e", UNIT_TESTS_ENV, "-t", "project",
+ "-y", UNIT_TESTS_INVENTORY, "-s", "-i", "admin",
+ "-p", "RegionOne", "-a", "Region", "-f", "name",
+ "-l", "ERROR"]
+
+LONG_COMMAND_ARGS = [
+ "scanner.py", "--mongo_config", "mongo_config_file",
+ "--env", UNIT_TESTS_ENV, "--type", "project",
+ "--inventory", UNIT_TESTS_INVENTORY, "--scan_self", "--id", "admin",
+ "--parent_id", "RegionOne", "--parent_type", "Region",
+ "--id_field", "name", "--loglevel", "ERROR",
+ "--clear"]
+
+LONG_COMMAND_ARGS_CLEAR_ALL = [
+ "scanner.py", "--mongo_config", "mongo_config_file",
+ "--env", UNIT_TESTS_ENV, "--type", "project",
+ "--inventory", UNIT_TESTS_INVENTORY, "--scan_self", "--id", "admin",
+ "--parent_id", "RegionOne", "--parent_type", "Region",
+ "--id_field", "name", "--loglevel", "ERROR",
+ "--clear_all"]
+
+LONG_COMMAND_ARGS_INVENTORY_ONLY = [
+ "scanner.py", "--mongo_config", "mongo_config_file",
+ "--env", UNIT_TESTS_ENV, "--type", "project",
+ "--inventory", UNIT_TESTS_INVENTORY, "--scan_self", "--id", "admin",
+ "--parent_id", "RegionOne", "--parent_type", "Region",
+ "--id_field", "name", "--loglevel", "ERROR", "--inventory_only",
+ "--clear"]
+
+LONG_COMMAND_ARGS_LINKS_ONLY = [
+ "scanner.py", "--mongo_config", "mongo_config_file",
+ "--env", UNIT_TESTS_ENV, "--type", "project",
+ "--inventory", UNIT_TESTS_INVENTORY, "--scan_self", "--id", "admin",
+ "--parent_id", "RegionOne", "--parent_type", "Region",
+ "--id_field", "name", "--loglevel", "ERROR", "--links_only",
+ "--clear"]
+
+LONG_COMMAND_ARGS_CLIQUES_ONLY = [
+ "scanner.py", "--mongo_config", "mongo_config_file",
+ "--env", UNIT_TESTS_ENV, "--type", "project",
+ "--inventory", UNIT_TESTS_INVENTORY, "--scan_self", "--id", "admin",
+ "--parent_id", "RegionOne", "--parent_type", "Region",
+ "--id_field", "name", "--loglevel", "ERROR", "--cliques_only",
+ "--clear"]
+
diff --git a/app/test/scan/test_data/scanner.py b/app/test/scan/test_data/scanner.py
new file mode 100644
index 0000000..cebeca2
--- /dev/null
+++ b/app/test/scan/test_data/scanner.py
@@ -0,0 +1,355 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import queue
+from discover.fetchers.folder_fetcher import FolderFetcher
+
+
+SCANNER_TYPE_FOR_ENV = "ScanEnvironment"
+
+METADATA = {
+ "scanners_package": "discover",
+ "scanners": {}
+}
+
+TYPE_TO_FETCH = {
+ "type": "pnic",
+ "fetcher": "CliFetchHostPnicsVpp",
+ "environment_condition": {"mechanism_drivers": "OVS"},
+ "children_scanner": "ScanOteps"
+}
+
+TYPE_TO_FETCH_WITH_WRONG_ENVIRONMENT_CONDITION = {
+ "type": "pnic",
+ "fetcher": "CliFetchHostPnicsVpp",
+ "environment_condition": {"mechanism_drivers": "VPP"},
+ "children_scanner": "ScanOteps"
+}
+
+TYPE_TO_FETCH_WITH_ERROR_VALUE = {
+ "environment_condition": {
+ "distribution": "Mirantis-7.0"
+ }
+}
+
+TYPE_TO_FETCH_WITHOUT_ENV_CON = {
+ "type": "pnic",
+ "fetcher": "CliFetchHostPnicsVpp",
+ "children_scanner": "ScanOteps"
+}
+
+TYPES_TO_FETCH = [
+ {
+ "type": "ports_folder",
+ "fetcher": FolderFetcher("ports", "network")
+ },
+ {
+ "type": "network_services_folder",
+ "fetcher": FolderFetcher("network_services", "network", "Network vServices")
+ }
+]
+
+ID_FIELD = "id"
+
+PROJECT1 = {
+ "object": {
+ "description": "",
+ "enabled": True,
+ "id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "name": "OSDNA-project"
+ },
+ "child_id_field": ID_FIELD,
+ "scanner": "ScanProject"
+}
+
+PROJECT2 = {
+ "object": {
+ "description": "admin tenant",
+ "enabled": True,
+ "id": "8c1751e0ce714736a63fee3c776164da",
+ "name": "admin"
+ },
+ "child_id_field": ID_FIELD,
+ "scanner": "ScanProject"
+}
+
+SCAN_QUEUE = queue.Queue()
+SCAN_QUEUE.put(PROJECT1)
+SCAN_QUEUE.put(PROJECT2)
+QUEUE_SIZE = 2
+
+LIMIT_TO_CHILD_TYPE = "ports_folder"
+
+CONFIGURATIONS = {
+ "configuration": [
+ {
+ "mock": "True",
+ "host": "10.56.20.239",
+ "name": "mysql",
+ "password": "102QreDdiD5sKcvNf9qbHrmr",
+ "port": 3307.0,
+ "user": "root",
+ "schema": "nova"
+ },
+ {
+ "name": "OpenStack",
+ "host": "10.56.20.239",
+ "admin_token": "38MUh19YWcgQQUlk2VEFQ7Ec",
+ "port": "5000",
+ "user": "admin",
+ "pwd": "admin"
+ },
+ {
+ "host": "10.56.20.239",
+ "key": "/Users/ngrandhi/.ssh/id_rsa",
+ "name": "CLI",
+ "pwd": "",
+ "user": "root"
+ },
+ {
+ "name": "AMQP",
+ "host": "10.56.20.239",
+ "port": "5673",
+ "user": "nova",
+ "password": "NF2nSv3SisooxPkCTr8fbfOa"
+ }
+ ],
+ "distribution": "Mirantis-8.0",
+ "last_scanned:": "5/8/16",
+ "name": "Mirantis-Liberty-Nvn",
+ "mechanism_drivers": [
+ "OVS"
+ ],
+ "operational": "yes",
+ "type": "environment"
+}
+
+TYPES_TO_FETCHES_FOR_PNIC = {
+ "type": "pnic",
+ "fetcher": "CliFetchHostPnicsVpp",
+ "environment_condition": {"mechanism_drivers": "VPP"},
+ "children_scanner": "ScanOteps"
+}
+
+TYPES_TO_FETCHES_FOR_PNIC_WITHOUT_ENV_CON = {
+ "type": "pnic",
+ "fetcher": "CliFetchHostPnicsVpp",
+ "children_scanner": "ScanOteps"
+}
+
+TYPES_TO_FETCHES_FOR_SCAN_AGGREGATE = [{
+ "type": "host_ref",
+ "fetcher": "DbFetchAggregateHosts"
+}]
+
+
+
+
+# id = 'RegionOne-aggregates'
+# obj = self.inv.get_by_id(self.env, id)
+obj = {'id': 'Mirantis-Liberty-Nvn'}
+id_field = 'id'
+child_id = '',
+child_type = ''
+
+
+child_data = [
+ {
+ 'id_path': '/Mirantis-Liberty-Nvn/Mirantis-Liberty-Nvn-regions',
+ 'object_name': 'Regions',
+ 'parent_id': 'Mirantis-Liberty-Nvn',
+ 'environment': 'Mirantis-Liberty-Nvn',
+ 'id': 'Mirantis-Liberty-Nvn-regions',
+ 'show_in_tree': True,
+ 'text': 'Regions',
+ 'type': 'regions_folder',
+ 'name': 'Regions',
+ 'create_object': True,
+ 'name_path': '/Mirantis-Liberty-Nvn/Regions',
+ 'parent_type': 'environment'
+ }
+]
+
+PARENT = {
+ "environment" : "Mirantis-Liberty-Xiaocong",
+ "id" : "node-6.cisco.com-vservices-dhcps",
+ "name" : "node-6.cisco.com-vservices-dhcps",
+ "object_name" : "DHCP servers",
+ "parent_id" : "node-6.cisco.com-vservices",
+ "parent_type" : "vservices_folder",
+ "show_in_tree" : True,
+ "text" : "DHCP servers",
+ "type" : "vservice_dhcps_folder"
+}
+
+PARENT_WITHOUT_ID = {
+ 'id': ''
+}
+
+TYPE_TO_FETCH_FOR_ENVIRONMENT = {
+ "type": "regions_folder",
+ "fetcher": FolderFetcher("regions", "environment"),
+ "children_scanner": "ScanRegionsRoot"
+}
+
+TYPE_TO_FETCH_FOR_ENV_WITHOUT_CHILDREN_FETCHER = {
+ "type": "regions_folder",
+ "fetcher": FolderFetcher("regions", "environment")
+}
+
+DB_RESULTS_WITH_CREATE_OBJECT = [
+ {
+ "name": "Mirantis-Liberty-Xiaocong-regions",
+ "parent_type": "environment",
+ "parent_id": "Mirantis-Liberty-Xiaocong",
+ "text": "Regions",
+ "create_object": True,
+ "type": "regions_folder",
+ "id": "Mirantis-Liberty-Xiaocong-regions"
+ }
+]
+
+DB_RESULTS_WITHOUT_CREATE_OBJECT = [
+ {
+ "name": "Mirantis-Liberty-Xiaocong-regions",
+ "parent_type": "environment",
+ "parent_id": "Mirantis-Liberty-Xiaocong",
+ "text": "Regions",
+ "create_object": False,
+ "type": "regions_folder",
+ "id": "Mirantis-Liberty-Xiaocong-regions"
+ }
+]
+
+DB_RESULTS_WITH_PROJECT = [
+ {
+ "name": "Mirantis-Liberty-Xiaocong-regions",
+ "parent_type": "environment",
+ "parent_id": "Mirantis-Liberty-Xiaocong",
+ "text": "Regions", "create_object": True,
+ "type": "regions_folder",
+ "id": "Mirantis-Liberty-Xiaocong-regions",
+ "in_project-OSDNA-project": "1",
+ }
+]
+
+PROJECT_KEY = "in_project-OSDNA-project"
+
+DB_RESULTS_WITH_MASTER_PARENT_IN_DB = [
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "local_service_id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-aiya",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ }
+]
+
+DB_RESULTS_WITHOUT_MASTER_PARENT_IN_DB = [
+ {
+ "host": "node-6.cisco.com",
+ "id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "local_service_id": "qdhcp-413de095-01ed-49dc-aa50-4479f43d390e",
+ "master_parent_id": "node-6.cisco.com-vservices",
+ "master_parent_type": "vservices_folder",
+ "name": "dhcp-aiya",
+ "parent_id": "node-6.cisco.com-vservices-dhcps",
+ "parent_text": "DHCP servers",
+ "parent_type": "vservice_dhcps_folder",
+ "service_type": "dhcp"
+ }
+]
+
+
+DICTIONARY_DB_RESULTS = {
+ "name": "Mirantis-Liberty-Xiaocong-regions",
+ "parent_type": "environment",
+ "parent_id": "Mirantis-Liberty-Xiaocong",
+ "text": "Regions", "create_object": True,
+ "type": "regions_folder",
+ "id": "Mirantis-Liberty-Xiaocong-regions"
+}
+
+MASTER_PARENT = {
+ "create_object" : True,
+ "environment" : "Mirantis-Liberty-Xiaocong",
+ "id" : "node-6.cisco.com-vservices",
+ "id_path" : "/Mirantis-Liberty/Mirantis-Liberty-regions/RegionOne/RegionOne-availability_zones/internal/node-6.cisco.com/node-6.cisco.com-vservices",
+ "name" : "Vservices",
+ "name_path" : "/Mirantis-Liberty/Regions/RegionOne/Availability Zones/internal/node-6.cisco.com/Vservices",
+ "object_name" : "Vservices",
+ "parent_id" : "node-6.cisco.com",
+ "parent_type" : "host",
+ "show_in_tree" : True,
+ "text" : "Vservices",
+ "type" : "vservices_folder"
+}
+
+CONFIGURATIONS_WITHOUT_MECHANISM_DRIVERS = {
+ "configuration": [
+ {
+ "mock": "True",
+ "host": "10.56.20.239",
+ "name": "mysql",
+ "password": "102QreDdiD5sKcvNf9qbHrmr",
+ "port": 3307.0,
+ "user": "root",
+ "schema": "nova"
+ },
+ {
+ "name": "OpenStack",
+ "host": "10.56.20.239",
+ "admin_token": "38MUh19YWcgQQUlk2VEFQ7Ec",
+ "port": "5000",
+ "user": "admin",
+ "pwd": "admin"
+ },
+ {
+ "host": "10.56.20.239",
+ "key": "/Users/ngrandhi/.ssh/id_rsa",
+ "name": "CLI",
+ "pwd": "",
+ "user": "root"
+ },
+ {
+ "name": "AMQP",
+ "host": "10.56.20.239",
+ "port": "5673",
+ "user": "nova",
+ "password": "NF2nSv3SisooxPkCTr8fbfOa"
+ }
+ ],
+ "distribution": "Mirantis-8.0",
+ "last_scanned:": "5/8/16",
+ "name": "Mirantis-Liberty-Nvn",
+ "operational": "yes",
+ "type": "environment"
+}
+
+SCAN_TYPE_RESULTS = [
+ {
+ "description": "",
+ "enabled": True,
+ "id": "75c0eb79ff4a42b0ae4973c8375ddf40",
+ "name": "OSDNA-project"
+ },
+ {
+ "description": "admin tenant",
+ "enabled": True,
+ "id": "8c1751e0ce714736a63fee3c776164da",
+ "name": "admin"
+ }
+]
+
+LIMIT_TO_CHILD_ID = "75c0eb79ff4a42b0ae4973c8375ddf40"
diff --git a/app/test/scan/test_scan.py b/app/test/scan/test_scan.py
new file mode 100644
index 0000000..a01083e
--- /dev/null
+++ b/app/test/scan/test_scan.py
@@ -0,0 +1,46 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import unittest
+from unittest.mock import MagicMock
+
+from discover.configuration import Configuration
+from monitoring.setup.monitoring_setup_manager import MonitoringSetupManager
+from test.scan.config.test_config \
+ import MONGODB_CONFIG, ENV_CONFIG, COLLECTION_CONFIG
+from test.scan.test_data.configurations import CONFIGURATIONS
+from utils.inventory_mgr import InventoryMgr
+from utils.mongo_access import MongoAccess
+from utils.logging.full_logger import FullLogger
+
+
+class TestScan(unittest.TestCase):
+
+ def configure_environment(self):
+ self.env = ENV_CONFIG
+ self.inventory_collection = COLLECTION_CONFIG
+ # mock the mongo access
+ MongoAccess.mongo_connect = MagicMock()
+ MongoAccess.db = MagicMock()
+ # mock log
+ FullLogger.info = MagicMock()
+
+ self.conf = Configuration()
+ self.conf.use_env = MagicMock()
+ self.conf.environment = CONFIGURATIONS
+ self.conf.configuration = CONFIGURATIONS["configuration"]
+
+ self.inv = InventoryMgr()
+ self.inv.clear = MagicMock()
+ self.inv.set_collections(self.inventory_collection)
+
+ MonitoringSetupManager.server_setup = MagicMock()
+
+ def setUp(self):
+ self.configure_environment()
diff --git a/app/test/scan/test_scan_controller.py b/app/test/scan/test_scan_controller.py
new file mode 100644
index 0000000..f3bcc9a
--- /dev/null
+++ b/app/test/scan/test_scan_controller.py
@@ -0,0 +1,215 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import sys
+from unittest.mock import MagicMock
+
+from discover.scan import ScanController, ScanPlan
+from discover.scanner import Scanner
+from test.scan.test_scan import TestScan
+from test.scan.test_data.scan import *
+from utils.inventory_mgr import InventoryMgr
+
+
+class TestScanController(TestScan):
+
+ def setUp(self):
+ super().setUp()
+ self.scan_controller = ScanController()
+
+ def arg_validate(self, args, expected, key, err=None):
+ if key not in expected:
+ return
+ err = err if err else 'The value of {} is wrong'.format(key)
+ self.assertEqual(args.get(key, None), expected[key.upper()], err)
+
+ def check_args_values(self, args, expected):
+ self.arg_validate(args, expected, 'env',
+ 'The value of environment is wrong')
+ keys = ['mongo_config', 'mongo_config', 'type', 'inventory',
+ 'scan_self', 'id', 'parent_id', 'parent_type', 'id_field',
+ 'loglevel', 'inventory_only', 'links_only', 'cliques_only',
+ 'clear']
+ for key in keys:
+ self.arg_validate(args, expected, key)
+
+ def test_get_args_with_default_arguments(self):
+ sys.argv = DEFAULT_COMMAND_ARGS
+ args = self.scan_controller.get_args()
+ # check the default value of each argument
+ self.check_args_values(args, DEFAULT_ARGUMENTS)
+
+ def test_get_args_with_short_command_args(self):
+ sys.argv = SHORT_COMMAND_ARGS
+ args = self.scan_controller.get_args()
+ # check the value parsed by short arguments
+ self.check_args_values(args, SHORT_FLAGS_ARGUMENTS)
+
+ def test_get_args_with_full_command_args(self):
+ sys.argv = LONG_COMMAND_ARGS
+ args = self.scan_controller.get_args()
+ # check the value parsed by long arguments
+ self.check_args_values(args, ARGUMENTS_FULL)
+
+ def test_get_args_with_full_command_args_clear_all(self):
+ sys.argv = LONG_COMMAND_ARGS_CLEAR_ALL
+ args = self.scan_controller.get_args()
+ # check the value parsed by long arguments
+ self.check_args_values(args, ARGUMENTS_FULL_CLEAR_ALL)
+
+ def test_get_args_with_full_command_args_inventory_only(self):
+ sys.argv = LONG_COMMAND_ARGS_INVENTORY_ONLY
+ args = self.scan_controller.get_args()
+ # check the value parsed by long arguments
+ self.check_args_values(args, ARGUMENTS_FULL_INVENTORY_ONLY)
+
+ def test_get_args_with_full_command_args_links_only(self):
+ sys.argv = LONG_COMMAND_ARGS_LINKS_ONLY
+ args = self.scan_controller.get_args()
+ # check the value parsed by long arguments
+ self.check_args_values(args, ARGUMENTS_FULL_LINKS_ONLY)
+
+ def test_get_args_with_full_command_args_cliques_only(self):
+ sys.argv = LONG_COMMAND_ARGS_CLIQUES_ONLY
+ args = self.scan_controller.get_args()
+ # check the value parsed by long arguments
+ self.check_args_values(args, ARGUMENTS_FULL_CLIQUES_ONLY)
+
+ def side_effect(self, key, default):
+ if key in FORM.keys():
+ return FORM[key]
+ else:
+ return default
+
+ def check_plan_values(self, plan, scanner_type, obj_id,
+ child_type, child_id):
+ self.assertEqual(scanner_type, plan.scanner_type,
+ 'The scanner class is wrong')
+ self.assertEqual(child_type, plan.child_type,
+ 'The child type is wrong')
+ self.assertEqual(child_id, plan.child_id,
+ 'The child id is wrong')
+ self.assertEqual(obj_id, plan.object_id, 'The object is wrong')
+
+ def test_prepare_scan_plan(self):
+ scan_plan = ScanPlan(SCAN_ENV_PLAN_TO_BE_PREPARED)
+ plan = self.scan_controller.prepare_scan_plan(scan_plan)
+ self.check_plan_values(plan, SCANNER_TYPE_FOR_ENV,
+ OBJ_ID_FOR_ENV, CHILD_TYPE_FOR_ENV,
+ CHILD_ID_FOR_ENV)
+
+ def test_prepare_scan_region_plan(self):
+ original_get_by_id = self.inv.get_by_id
+ self.inv.get_by_id = MagicMock(return_value=REGIONS_FOLDER)
+
+ self.scan_controller.inv = self.inv
+ scan_plan = ScanPlan(SCAN_REGION_PLAN_TO_BE_PREPARED)
+ plan = self.scan_controller.prepare_scan_plan(scan_plan)
+
+ self.check_plan_values(plan, SCANNER_TYPE_FOR_REGION,
+ OBJ_ID_FOR_REGION, CHILD_TYPE_FOR_REGION,
+ CHILD_ID_FOR_REGION)
+ self.inv.get_by_id = original_get_by_id
+
+ def test_prepare_scan_region_folder_plan(self):
+ scan_plan = ScanPlan(SCAN_REGION_FOLDER_PLAN_TO_BE_PREPARED)
+ plan = self.scan_controller.prepare_scan_plan(scan_plan)
+ self.check_plan_values(plan, SCANNER_CLASS_FOR_REGION_FOLDER,
+ OBJ_ID_FOR_REGION_FOLDER,
+ CHILD_TYPE_FOR_REGION_FOLDER,
+ CHILD_ID_FOR_REGION_FOLDER)
+
+ def check_scan_method_calls(self, mock, count):
+ if count:
+ self.assertTrue(mock.called)
+ else:
+ mock.assert_not_called()
+
+ def check_scan_counts(self, run_scan_count, scan_links_count,
+ scan_cliques_count, deploy_monitoring_setup_count):
+ self.check_scan_method_calls(Scanner.scan, run_scan_count)
+ self.check_scan_method_calls(Scanner.scan_links, scan_links_count)
+ self.check_scan_method_calls(Scanner.scan_cliques, scan_cliques_count)
+ self.check_scan_method_calls(Scanner.deploy_monitoring_setup,
+ deploy_monitoring_setup_count)
+
+ def prepare_scan_mocks(self):
+ self.load_metadata = Scanner.load_metadata
+ self.scan = Scanner.scan
+ self.scan_links = Scanner.scan_links
+ self.scan_cliques = Scanner.scan_cliques
+ self.deploy_monitoring_setup = Scanner.deploy_monitoring_setup
+
+ Scanner.load_metadata = MagicMock()
+ Scanner.scan = MagicMock()
+ Scanner.scan_links = MagicMock()
+ Scanner.scan_cliques = MagicMock()
+ Scanner.deploy_monitoring_setup = MagicMock()
+
+ def reset_methods(self):
+ Scanner.load_metadata = self.load_metadata
+ Scanner.scan = self.scan
+ Scanner.scan_links = self.scan_links
+ Scanner.scan_cliques = self.scan_cliques
+ Scanner.deploy_monitoring_setup = self.deploy_monitoring_setup
+
+ def test_scan(self):
+ self.scan_controller.get_args = MagicMock()
+ InventoryMgr.is_feature_supported = MagicMock(return_value=False)
+ plan = self.scan_controller.prepare_scan_plan(ScanPlan(SCAN_ENV_PLAN_TO_BE_PREPARED))
+ self.scan_controller.get_scan_plan = MagicMock(return_value=plan)
+ self.prepare_scan_mocks()
+
+ self.scan_controller.run()
+ self.check_scan_counts(1, 1, 1, 0)
+ self.reset_methods()
+
+ def test_scan_with_monitoring_setup(self):
+ self.scan_controller.get_args = MagicMock()
+ InventoryMgr.is_feature_supported = MagicMock(return_value=True)
+ plan = self.scan_controller.prepare_scan_plan(ScanPlan(SCAN_ENV_PLAN_TO_BE_PREPARED))
+ self.scan_controller.get_scan_plan = MagicMock(return_value=plan)
+ self.prepare_scan_mocks()
+
+ self.scan_controller.run()
+ self.check_scan_counts(1, 1, 1, 1)
+ self.reset_methods()
+
+ def test_scan_with_inventory_only(self):
+ self.scan_controller.get_args = MagicMock()
+ scan_plan = ScanPlan(SCAN_ENV_INVENTORY_ONLY_PLAN_TO_BE_PREPARED)
+ plan = self.scan_controller.prepare_scan_plan(scan_plan)
+ self.scan_controller.get_scan_plan = MagicMock(return_value=plan)
+ self.prepare_scan_mocks()
+
+ self.scan_controller.run()
+ self.check_scan_counts(1, 0, 0, 0)
+ self.reset_methods()
+
+ def test_scan_with_links_only(self):
+ self.scan_controller.get_args = MagicMock()
+ scan_plan = ScanPlan(SCAN_ENV_LINKS_ONLY_PLAN_TO_BE_PREPARED)
+ plan = self.scan_controller.prepare_scan_plan(scan_plan)
+ self.scan_controller.get_scan_plan = MagicMock(return_value=plan)
+ self.prepare_scan_mocks()
+
+ self.scan_controller.run()
+ self.check_scan_counts(0, 1, 0, 0)
+ self.reset_methods()
+
+ def test_scan_with_cliques_only(self):
+ self.scan_controller.get_args = MagicMock()
+ scan_plan = ScanPlan(SCAN_ENV_CLIQUES_ONLY_PLAN_TO_BE_PREPARED)
+ plan = self.scan_controller.prepare_scan_plan(scan_plan)
+ self.scan_controller.get_scan_plan = MagicMock(return_value=plan)
+ self.prepare_scan_mocks()
+
+ self.scan_controller.run()
+ self.check_scan_counts(0, 0, 1, 0)
+ self.reset_methods()
diff --git a/app/test/scan/test_scan_metadata_parser.py b/app/test/scan/test_scan_metadata_parser.py
new file mode 100644
index 0000000..91c11ef
--- /dev/null
+++ b/app/test/scan/test_scan_metadata_parser.py
@@ -0,0 +1,152 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.fetchers.db.db_access import DbAccess
+from discover.scan_metadata_parser import ScanMetadataParser
+from test.scan.test_scan import TestScan
+from test.scan.test_data.metadata import *
+from unittest import mock
+from utils.mongo_access import MongoAccess
+
+
+SCANNERS_FILE = 'scanners.json'
+
+JSON_REQUIRED_FIELDS_ERROR = 'Metadata json should contain all the ' + \
+ 'following fields: scanners_package, scanners'
+
+JSON_NO_SCANNERS = 'no scanners found in scanners list'
+JSON_ERRORS_FOUND = 'Errors encountered during metadata file parsing:\n'
+
+
+class TestScanMetadataParser(TestScan):
+ def setUp(self):
+ super().setUp()
+ DbAccess.conn = mock.MagicMock()
+ self.prepare_constants()
+ self.parser = ScanMetadataParser(self.inv)
+
+ self.parser.check_metadata_file_ok = mock.MagicMock()
+
+ def prepare_metadata(self, content):
+ self.parser._load_json_file = mock.MagicMock(return_value=content)
+
+ def prepare_constants(self):
+ MongoAccess.db = mock.MagicMock()
+ MongoAccess.db["constants"].find_one = mock.MagicMock(side_effect=
+ lambda input:
+ CONSTANTS[input["name"]]
+ if CONSTANTS.get(input["name"])
+ else []
+ )
+
+ def handle_error_scenario(self, input_content, expected_error,
+ add_errors_encountered_pretext=True):
+ self.prepare_metadata(input_content)
+ found_exception = False
+ expected_message = expected_error
+ metadata = None
+ try:
+ metadata = self.parser.parse_metadata_file(SCANNERS_FILE)
+ except ValueError as e:
+ found_exception = True
+ expected_message = expected_error \
+ if not add_errors_encountered_pretext \
+ else JSON_ERRORS_FOUND + expected_error
+ self.assertEqual(str(e), expected_message)
+ self.assertTrue(found_exception,
+ 'failed to throw exception, expected_message: {}'
+ .format(expected_message))
+ self.assertIsNone(metadata)
+
+ def handle_json_missing_field(self, json_content):
+ self.handle_error_scenario(json_content, JSON_REQUIRED_FIELDS_ERROR,
+ add_errors_encountered_pretext=False)
+
+ def test_missing_field(self):
+ for content in [METADATA_EMPTY, METADATA_NO_PACKAGE,
+ METADATA_NO_SCANNERS]:
+ self.handle_json_missing_field(content)
+
+ def test_json_no_scanners(self):
+ self.handle_error_scenario(METADATA_ZERO_SCANNERS, JSON_NO_SCANNERS)
+
+ def test_json_scanner_errors(self):
+ errors_scenarios = [
+ {
+ 'input': METADATA_ZERO_SCANNERS,
+ 'msg': JSON_NO_SCANNERS
+ },
+ {
+ 'input': METADATA_SCANNER_UNKNOWN_ATTRIBUTE,
+ 'msg': 'unknown attribute xyz in scanner ScanAggregate, type #1'
+ },
+ {
+ 'input': METADATA_SCANNER_NO_TYPE,
+ 'msg': 'scanner ScanAggregate, type #1: ' +
+ 'missing attribute "type"'
+ },
+ {
+ 'input': METADATA_SCANNER_NO_FETCHER,
+ 'msg': 'scanner ScanAggregate, type #1: ' +
+ 'missing attribute "fetcher"'
+ },
+ {
+ 'input': METADATA_SCANNER_INCORRECT_TYPE,
+ 'msg': 'scanner ScanAggregate: value not in types: t1'
+ },
+ {
+ 'input': METADATA_SCANNER_INCORRECT_FETCHER,
+ 'msg': 'failed to find fetcher class f1 '
+ 'in scanner ScanAggregate type #1'
+ },
+ {
+ 'input': METADATA_SCANNER_WITH_INCORRECT_CHILD,
+ 'msg': 'scanner ScanAggregatesRoot type #1: '
+ 'children_scanner must be a string'
+ },
+ {
+ 'input': METADATA_SCANNER_WITH_MISSING_CHILD,
+ 'msg': 'scanner ScanAggregatesRoot type #1: '
+ 'children_scanner ScanAggregate not found '
+ },
+ {
+ 'input': METADATA_SCANNER_FETCHER_INVALID_DICT,
+ 'msg': 'scanner ScanEnvironment type #1: '
+ 'only folder dict accepted in fetcher'
+ },
+ {
+ 'input': METADATA_SCANNER_WITH_INVALID_CONDITION,
+ 'msg': 'scanner ScanHost type #1: condition must be dict'
+ }
+ ]
+ for scenario in errors_scenarios:
+ self.handle_error_scenario(scenario['input'], scenario['msg'])
+
+ def check_json_is_ok(self, json_content):
+ self.prepare_metadata(json_content)
+ found_exception = False
+ metadata = None
+ msg = None
+ try:
+ metadata = self.parser.parse_metadata_file(SCANNERS_FILE)
+ except ValueError as e:
+ found_exception = True
+ msg = str(e)
+ self.assertFalse(found_exception, 'Exception: {}'.format(msg))
+ self.assertIsNotNone(metadata)
+
+ def test_json_valid_content(self):
+ valid_content = [
+ METADATA_SIMPLE_SCANNER,
+ METADATA_SCANNER_WITH_CHILD,
+ METADATA_SCANNER_WITH_FOLDER,
+ METADATA_SCANNER_WITH_CONDITION
+ ]
+ for content in valid_content:
+ self.check_json_is_ok(content)
diff --git a/app/test/scan/test_scanner.py b/app/test/scan/test_scanner.py
new file mode 100644
index 0000000..4a7536e
--- /dev/null
+++ b/app/test/scan/test_scanner.py
@@ -0,0 +1,355 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+from discover.scanner import Scanner
+from test.scan.test_scan import TestScan
+from unittest.mock import MagicMock, patch
+from discover.scan_metadata_parser import ScanMetadataParser
+from test.scan.test_data.scanner import *
+from monitoring.setup.monitoring_setup_manager import MonitoringSetupManager
+
+
+class TestScanner(TestScan):
+
+ def setUp(self):
+ super().setUp()
+ ScanMetadataParser.parse_metadata_file = MagicMock(return_value=METADATA)
+ self.scanner = Scanner()
+ self.scanner.set_env(self.env)
+ MonitoringSetupManager.create_setup = MagicMock()
+ self.scanner.inv.monitoring_setup_manager = \
+ MonitoringSetupManager(self.env)
+
+ def test_check_type_env_without_environment_condition(self):
+ result = self.scanner.check_type_env(TYPE_TO_FETCH_WITHOUT_ENV_CON)
+
+ self.assertEqual(result, True,
+ "Can't get true when the type_to_fetch " +
+ "doesn't contain environment condition")
+
+ def test_check_type_with_error_value(self):
+ # store original method
+ original_get_env_config = self.scanner.config.get_env_config
+
+ # mock get_env_config method
+ self.scanner.config.get_env_config =\
+ MagicMock(return_value=CONFIGURATIONS)
+
+ result = self.scanner.check_type_env(TYPE_TO_FETCH_WITH_ERROR_VALUE)
+
+ # reset get_env_config method
+ self.scanner.config.get_env_config = original_get_env_config
+
+ self.assertEqual(result, False,
+ "Can't get false when the type_to_fetch " +
+ "contain error value")
+
+ def test_check_type_env_without_mechanism_drivers_in_env_config(self):
+ # store original method
+ original_get_env_config = self.scanner.config.get_env_config
+
+ # mock get_env_config_method
+ self.scanner.config.get_env_config =\
+ MagicMock(return_value=CONFIGURATIONS_WITHOUT_MECHANISM_DRIVERS)
+
+ result = self.scanner.check_type_env(TYPE_TO_FETCH)
+ # reset get_env_config method
+ self.scanner.check_type_env = original_get_env_config
+
+ self.assertEqual(result, False,
+ "Can't get false when configuration " +
+ "doesn't contain mechanism drivers")
+
+ def test_check_type_env_with_wrong_mech_drivers_in_env_condition(self):
+ # store original method
+ original_get_env_config = self.scanner.config.get_env_config
+
+ # mock get_env_config_method
+ self.scanner.config.get_env_config =\
+ MagicMock(return_value=CONFIGURATIONS)
+
+ result = self.scanner.\
+ check_type_env(TYPE_TO_FETCH_WITH_WRONG_ENVIRONMENT_CONDITION)
+ # reset get_env_config method
+ self.scanner.check_type_env = original_get_env_config
+
+ self.assertEqual(result, False, "Can't get false when the mechanism " +
+ "drivers in type_to_fetch " +
+ "don't exist in configurations")
+
+ def test_check_type_env(self):
+ # store original method
+ original_get_env_config = self.scanner.config.get_env_config
+
+ # mock method
+ self.scanner.config.get_env_config =\
+ MagicMock(return_value=CONFIGURATIONS)
+
+ result = self.scanner.check_type_env(TYPE_TO_FETCH)
+
+ # reset method
+ self.scanner.config.get_env_config = original_get_env_config
+
+ self.assertEqual(result, True,
+ "Can't get True when the type_to_fetch is correct")
+
+ def test_scan_error_type(self):
+ # store original method
+ original_check_type_env = self.scanner.check_type_env
+
+ # mock method
+ self.scanner.check_type_env = MagicMock(return_value=False)
+
+ result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
+ ID_FIELD)
+
+ # reset method
+ self.scanner.check_type_env = original_check_type_env
+
+ self.assertEqual(result, [],
+ "Can't get [], when the type_to_fetch is wrong")
+
+ def test_scan_type_without_parent_id(self):
+ try:
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT,
+ PARENT_WITHOUT_ID, ID_FIELD)
+ self.fail("Can't get error when the parent " +
+ "doesn't contain id attribute")
+ except:
+ pass
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_with_get_exception(self, fetcher_get):
+ fetcher_get.side_effect = Exception("get exception")
+
+ try:
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT,
+ PARENT, ID_FIELD)
+ self.fail("Can't get exception when fetcher.get throws an exception")
+ except:
+ pass
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_without_master_parent(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITHOUT_MASTER_PARENT_IN_DB
+
+ # store original get_by_id
+ original_get_by_id = self.scanner.inv.get_by_id
+ original_set = self.scanner.inv.set
+
+ # mock methods
+ self.scanner.inv.get_by_id = MagicMock(return_value=[])
+
+ result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
+ ID_FIELD)
+
+ # reset methods
+ self.scanner.inv.get_by_id = original_get_by_id
+ self.scanner.inv.set = original_set
+ self.assertEqual(result, [], "Can't get [], when the master parent " +
+ "doesn't exist in database")
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_with_master_parent(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITH_MASTER_PARENT_IN_DB
+
+ # store original methods
+ original_get_by_id = self.scanner.inv.get_by_id
+ original_set = self.scanner.inv.set
+
+ # mock methods
+ self.scanner.inv.get_by_id = MagicMock(return_value=MASTER_PARENT)
+ self.scanner.inv.set = MagicMock()
+
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
+ self.assertEqual(self.scanner.inv.set.call_count, 2, "Can't create additional folder")
+ self.assertNotIn("master_parent_type", DB_RESULTS_WITH_MASTER_PARENT_IN_DB, "Can't delete the master_parent_type")
+ self.assertNotIn("master_parent_id", DB_RESULTS_WITH_MASTER_PARENT_IN_DB, "Can't delete the master_parent_id")
+
+ # reset methods
+ self.scanner.inv.get_by_id = original_get_by_id
+ self.scanner.inv.set = original_set
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_with_in_project(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITH_PROJECT
+
+ # store original method
+ original_set = self.scanner.inv.set
+
+ # mock method
+ self.scanner.inv.set = MagicMock()
+
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
+ self.assertIn("projects", DB_RESULTS_WITH_PROJECT[0],
+ "Can't get the projects from DB result")
+ self.assertNotIn(PROJECT_KEY, DB_RESULTS_WITH_PROJECT[0],
+ "Can't delete the project key in the object")
+
+ self.scanner.inv.set = original_set
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_without_create_object(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITHOUT_CREATE_OBJECT
+
+ original_set = self.scanner.inv.set
+
+ self.scanner.inv.set = MagicMock()
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
+
+ self.assertEqual(self.scanner.inv.set.call_count, 0,
+ "Set the object when the create object is false")
+
+ self.scanner.inv.set = original_set
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_with_create_object(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT
+
+ original_set = self.scanner.inv.set
+
+ self.scanner.inv.set = MagicMock()
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
+
+ self.assertEqual(self.scanner.inv.set.call_count, 1,
+ "Set the object when the create object is false")
+
+ self.scanner.inv.set = original_set
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_with_children_scanner(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT
+
+ original_set = self.scanner.inv.set
+ original_queue_for_scan = self.scanner.queue_for_scan
+
+ self.scanner.inv.set = MagicMock()
+ self.scanner.queue_for_scan = MagicMock()
+
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT, ID_FIELD)
+
+ self.assertEqual(self.scanner.queue_for_scan.call_count, 1,
+ "Can't put children scanner in the queue")
+
+ self.scanner.inv.set = original_set
+ self.scanner.queue_for_scan = original_queue_for_scan
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type_without_children_scanner(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT
+
+ original_set = self.scanner.inv.set
+ original_queue_for_scan = self.scanner.queue_for_scan
+
+ self.scanner.inv.set = MagicMock()
+ self.scanner.queue_for_scan = MagicMock()
+
+ self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENV_WITHOUT_CHILDREN_FETCHER,
+ PARENT, ID_FIELD)
+
+ self.assertEqual(self.scanner.queue_for_scan.call_count, 0,
+ "Can't put children scanner in the queue")
+
+ self.scanner.inv.set = original_set
+ self.scanner.queue_for_scan = original_queue_for_scan
+
+ @patch("discover.fetchers.folder_fetcher.FolderFetcher.get")
+ def test_scan_type(self, fetcher_get):
+ fetcher_get.return_value = DB_RESULTS_WITH_CREATE_OBJECT
+
+ original_set = self.scanner.inv.set
+ original_queue_for_scan = self.scanner.queue_for_scan
+
+ self.scanner.inv.set = MagicMock()
+ self.scanner.queue_for_scan = MagicMock()
+
+ result = self.scanner.scan_type(TYPE_TO_FETCH_FOR_ENVIRONMENT, PARENT,
+ ID_FIELD)
+
+ self.assertNotEqual(result, [], "Can't get children form scan_type")
+
+ self.scanner.inv.set = original_set
+ self.scanner.queue_for_scan = original_queue_for_scan
+
+ def test_scan_with_limit_to_child_type(self):
+ original_scan_type = self.scanner.scan_type
+ original_get_scanner = self.scanner.get_scanner
+
+ self.scanner.scan_type = MagicMock(return_value=[])
+ self.scanner.get_scanner = MagicMock(return_value=TYPES_TO_FETCH)
+
+ limit_to_child_type = TYPES_TO_FETCH[0]['type']
+
+ self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT, limit_to_child_type=limit_to_child_type)
+
+ # only scan the limit child type
+ self.scanner.scan_type.assert_called_with(TYPES_TO_FETCH[0], PARENT,
+ ID_FIELD)
+
+ self.scanner.scan_type = original_scan_type
+ self.scanner.get_scanner = original_get_scanner
+
+ def test_scan_with_limit_to_child_id(self):
+ original_scan_type = self.scanner.scan_type
+ original_get_scanner = self.scanner.get_scanner
+
+ self.scanner.get_scanner = MagicMock(return_value=TYPES_TO_FETCH)
+ limit_to_child_id = SCAN_TYPE_RESULTS[0][ID_FIELD]
+
+ self.scanner.scan_type = MagicMock(return_value=SCAN_TYPE_RESULTS)
+
+ children = self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT, id_field=ID_FIELD,
+ limit_to_child_id=limit_to_child_id)
+
+ # only get the limit child
+ self.assertEqual(children, SCAN_TYPE_RESULTS[0])
+
+ self.scanner.scan_type = original_scan_type
+ self.scanner.get_scanner = original_get_scanner
+
+ def test_scan(self):
+ original_scan_type = self.scanner.scan_type
+ original_get_scanner = self.scanner.get_scanner
+
+ self.scanner.get_scanner = MagicMock(return_values=TYPES_TO_FETCH)
+ result = self.scanner.scan(SCANNER_TYPE_FOR_ENV, PARENT)
+
+ self.assertEqual(PARENT, result,
+ "Can't get the original parent after the scan")
+
+ self.scanner.get_scanner = original_get_scanner
+ self.scanner.scan_type = original_scan_type
+
+ def test_run_scan(self):
+ original_scan = self.scanner.scan
+ original_scan_from_queue = self.scanner.scan_from_queue
+
+ self.scanner.scan = MagicMock()
+ self.scanner.scan_from_queue = MagicMock()
+
+ self.scanner.run_scan(SCANNER_TYPE_FOR_ENV, PARENT, ID_FIELD, LIMIT_TO_CHILD_ID,
+ LIMIT_TO_CHILD_TYPE)
+
+ self.scanner.scan.assert_called_with(SCANNER_TYPE_FOR_ENV, PARENT, ID_FIELD,
+ LIMIT_TO_CHILD_ID,
+ LIMIT_TO_CHILD_TYPE)
+ self.scanner.scan_from_queue.assert_any_call()
+
+ self.scanner.scan = original_scan
+ self.scanner.scan_from_queue = original_scan_from_queue
+
+ @patch("discover.scanner.Scanner.scan")
+ def test_scan_from_queue(self, scan):
+ scan.return_value = []
+ Scanner.scan_queue = SCAN_QUEUE
+
+ self.scanner.scan_from_queue()
+
+ self.assertEqual(self.scanner.scan.call_count, QUEUE_SIZE,
+ "Can't scan all the objects in the queue")
diff --git a/app/test/test_suite.py b/app/test/test_suite.py
new file mode 100644
index 0000000..00e7492
--- /dev/null
+++ b/app/test/test_suite.py
@@ -0,0 +1,25 @@
+###############################################################################
+# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) #
+# and others #
+# #
+# All rights reserved. This program and the accompanying materials #
+# are made available under the terms of the Apache License, Version 2.0 #
+# which accompanies this distribution, and is available at #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+###############################################################################
+import argparse
+import unittest
+
+
+def get_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-d", "--dir", dest="start_dir", nargs="?",
+ type=str, default=".",
+ help="Name of root directory for test cases discovery")
+
+ return parser.parse_args()
+
+if __name__ == "__main__":
+ args = get_args()
+ suite = unittest.TestLoader().discover(start_dir=args.start_dir)
+ unittest.TextTestRunner(verbosity=2).run(suite) \ No newline at end of file