| #!/usr/bin/env python3 |
| """ |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| """ |
| |
| from unittest import TestCase |
| import os |
| |
| |
| class TestStackAdvisorInitialization(TestCase): |
| def setUp(self): |
| import imp |
| |
| self.test_directory = os.path.dirname(os.path.abspath(__file__)) |
| resources_path = os.path.join(self.test_directory, "../../main/resources") |
| stack_advisor_path = os.path.abspath( |
| os.path.join(resources_path, "scripts/stack_advisor.py") |
| ) |
| |
| ambari_configuration_path = os.path.abspath( |
| os.path.join(resources_path, "stacks/ambari_configuration.py") |
| ) |
| with open(ambari_configuration_path, "rb") as fp: |
| imp.load_module( |
| "ambari_configuration", |
| fp, |
| ambari_configuration_path, |
| (".py", "rb", imp.PY_SOURCE), |
| ) |
| |
| with open(stack_advisor_path, "rb") as fp: |
| self.stack_advisor = imp.load_module( |
| "stack_advisor", fp, stack_advisor_path, (".py", "rb", imp.PY_SOURCE) |
| ) |
| |
| def test_stackAdvisorLoadedForNotHDPStack(self): |
| path_template = os.path.join( |
| self.test_directory, "../resources/stacks/{0}/{1}/services/stack_advisor.py" |
| ) |
| path_template_name = "STACK_ADVISOR_IMPL_PATH_TEMPLATE" |
| setattr(self.stack_advisor, path_template_name, path_template) |
| self.assertEqual(path_template, getattr(self.stack_advisor, path_template_name)) |
| instantiate_stack_advisor_method_name = "instantiateStackAdvisor" |
| instantiate_stack_advisor_method = getattr( |
| self.stack_advisor, instantiate_stack_advisor_method_name |
| ) |
| stack_advisor = instantiate_stack_advisor_method("XYZ", "1.0.1", ["1.0.0"]) |
| self.assertEqual("XYZ101StackAdvisor", stack_advisor.__class__.__name__) |
| services = { |
| "Versions": {"stack_name": "XYZ", "stack_version": "1.0.1"}, |
| "services": [ |
| { |
| "StackServices": {"service_name": "YARN"}, |
| "components": [ |
| {"StackServiceComponents": {"component_name": "RESOURCEMANAGER"}}, |
| {"StackServiceComponents": {"component_name": "APP_TIMELINE_SERVER"}}, |
| {"StackServiceComponents": {"component_name": "YARN_CLIENT"}}, |
| {"StackServiceComponents": {"component_name": "NODEMANAGER"}}, |
| ], |
| } |
| ], |
| } |
| hosts = { |
| "items": [{"Hosts": {"host_name": "host1"}}, {"Hosts": {"host_name": "host2"}}] |
| } |
| config_recommendations = stack_advisor.recommendConfigurations(services, hosts) |
| yarn_configs = config_recommendations["recommendations"]["blueprint"][ |
| "configurations" |
| ]["yarn-site"]["properties"] |
| """Check that value is populated from child class, not parent""" |
| self.assertEqual("-Xmx101m", yarn_configs["yarn.nodemanager.resource.memory-mb"]) |
| |
| def test_stackAdvisorDefaultImpl(self): |
| instantiate_stack_advisor_method_name = "instantiateStackAdvisor" |
| instantiate_stack_advisor_method = getattr( |
| self.stack_advisor, instantiate_stack_advisor_method_name |
| ) |
| """Not existent stack - to return default implementation""" |
| default_stack_advisor = instantiate_stack_advisor_method("HDP1", "2.0.6", []) |
| self.assertEqual("DefaultStackAdvisor", default_stack_advisor.__class__.__name__) |
| services = { |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| "services": [ |
| { |
| "StackServices": { |
| "service_name": "GANGLIA", |
| "service_version": "3.5.0", |
| }, |
| "components": [ |
| { |
| "StackServiceComponents": { |
| "cardinality": "ALL", |
| "component_name": "GANGLIA_MONITOR", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1", |
| "component_name": "GANGLIA_SERVER", |
| "is_master": True, |
| "hostnames": [], |
| } |
| }, |
| ], |
| }, |
| { |
| "StackServices": {"service_name": "HBASE", "service_version": "0.98.0.2.1"}, |
| "components": [ |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_name": "HBASE_CLIENT", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_name": "HBASE_MASTER", |
| "is_master": True, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_name": "HBASE_REGIONSERVER", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| ], |
| }, |
| { |
| "StackServices": {"service_name": "HDFS", "service_version": "2.4.0.2.1"}, |
| "components": [ |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_name": "DATANODE", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_name": "HDFS_CLIENT", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "0+", |
| "component_name": "JOURNALNODE", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1-2", |
| "component_name": "NAMENODE", |
| "is_master": True, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1", |
| "component_name": "SECONDARY_NAMENODE", |
| "is_master": True, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "0+", |
| "component_name": "ZKFC", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| ], |
| }, |
| { |
| "StackServices": {"service_name": "PIG", "service_version": "0.12.1.2.1"}, |
| "components": [ |
| { |
| "StackServiceComponents": { |
| "cardinality": "0+", |
| "component_name": "PIG", |
| "is_master": False, |
| "hostnames": [], |
| } |
| } |
| ], |
| }, |
| { |
| "StackServices": {"service_name": "TEZ", "service_version": "0.4.0.2.1"}, |
| "components": [ |
| { |
| "StackServiceComponents": { |
| "cardinality": "0+", |
| "component_name": "TEZ_CLIENT", |
| "is_master": False, |
| "hostnames": [], |
| } |
| } |
| ], |
| }, |
| { |
| "StackServices": { |
| "service_name": "ZOOKEEPER", |
| "service_version": "3.4.5.2.1", |
| }, |
| "components": [ |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_category": "CLIENT", |
| "component_name": "ZOOKEEPER_CLIENT", |
| "is_master": False, |
| "hostnames": [], |
| } |
| }, |
| { |
| "StackServiceComponents": { |
| "cardinality": "1+", |
| "component_name": "ZOOKEEPER_SERVER", |
| "is_master": True, |
| "hostnames": [], |
| } |
| }, |
| ], |
| }, |
| ], |
| "configurations": {}, |
| } |
| hosts = { |
| "items": [ |
| { |
| "Hosts": { |
| "host_name": "host1", |
| "cpu_count": 1, |
| "total_mem": 2097152, |
| "disk_info": [{"size": "80000000", "mountpoint": "/"}], |
| } |
| }, |
| { |
| "Hosts": { |
| "host_name": "host2", |
| "cpu_count": 1, |
| "total_mem": 2097152, |
| "disk_info": [{"size": "80000000", "mountpoint": "/"}], |
| } |
| }, |
| ] |
| } |
| actualValidateConfigResponse = default_stack_advisor.validateConfigurations( |
| services, hosts |
| ) |
| actualValidateLayoutResponse = default_stack_advisor.validateComponentLayout( |
| services, hosts |
| ) |
| expectedValidationResponse = { |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| "items": [], |
| } |
| self.assertEqual(actualValidateConfigResponse, expectedValidationResponse) |
| self.assertEqual(actualValidateLayoutResponse, expectedValidationResponse) |
| actualRecommendConfigResponse = default_stack_advisor.recommendConfigurations( |
| services, hosts |
| ) |
| expectedRecommendConfigResponse = { |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| "hosts": ["host1", "host2"], |
| "services": ["GANGLIA", "HBASE", "HDFS", "PIG", "TEZ", "ZOOKEEPER"], |
| "recommendations": { |
| "blueprint": {"configurations": {}, "host_groups": []}, |
| "blueprint_cluster_binding": {"host_groups": []}, |
| }, |
| } |
| self.assertEqual(actualRecommendConfigResponse, expectedRecommendConfigResponse) |
| actualRecommendLayoutResponse = default_stack_advisor.recommendComponentLayout( |
| services, hosts |
| ) |
| expectedRecommendLayoutResponse = { |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| "hosts": ["host1", "host2"], |
| "services": ["GANGLIA", "HBASE", "HDFS", "PIG", "TEZ", "ZOOKEEPER"], |
| "recommendations": { |
| "blueprint": { |
| "host_groups": [ |
| {"name": "host-group-2", "components": []}, |
| { |
| "name": "host-group-1", |
| "components": [ |
| {"name": "GANGLIA_SERVER"}, |
| {"name": "HBASE_MASTER"}, |
| {"name": "NAMENODE"}, |
| {"name": "SECONDARY_NAMENODE"}, |
| {"name": "ZOOKEEPER_SERVER"}, |
| {"name": "ZOOKEEPER_CLIENT"}, |
| ], |
| }, |
| ] |
| }, |
| "blueprint_cluster_binding": { |
| "host_groups": [ |
| {"name": "host-group-2", "hosts": [{"fqdn": "host2"}]}, |
| {"name": "host-group-1", "hosts": [{"fqdn": "host1"}]}, |
| ] |
| }, |
| }, |
| } |
| self.assertEqual(actualRecommendLayoutResponse, expectedRecommendLayoutResponse) |
| |
| # Test with maintenance_state. One host is in maintenance mode. |
| hosts = { |
| "items": [ |
| {"Hosts": {"host_name": "host1", "maintenance_state": "OFF", "cpu_count": 1}}, |
| {"Hosts": {"host_name": "host2", "maintenance_state": "ON", "cpu_count": 1}}, |
| ] |
| } |
| |
| actualRecommendLayoutResponse = default_stack_advisor.recommendComponentLayout( |
| services, hosts |
| ) |
| expectedRecommendLayoutResponse = { |
| "services": ["GANGLIA", "HBASE", "HDFS", "PIG", "TEZ", "ZOOKEEPER"], |
| "recommendations": { |
| "blueprint": { |
| "host_groups": [ |
| { |
| "name": "host-group-1", |
| "components": [ |
| {"name": "GANGLIA_SERVER"}, |
| {"name": "HBASE_MASTER"}, |
| {"name": "NAMENODE"}, |
| {"name": "SECONDARY_NAMENODE"}, |
| {"name": "ZOOKEEPER_SERVER"}, |
| {"name": "ZOOKEEPER_CLIENT"}, |
| ], |
| } |
| ] |
| }, |
| "blueprint_cluster_binding": { |
| "host_groups": [{"hosts": [{"fqdn": "host1"}], "name": "host-group-1"}] |
| }, |
| }, |
| "hosts": ["host1"], |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| } |
| self.assertEqual(actualRecommendLayoutResponse, expectedRecommendLayoutResponse) |
| |
| # Test with maintenance_state. Both hosts are in maintenance mode. |
| hosts = { |
| "items": [ |
| { |
| "Hosts": { |
| "host_name": "host1", |
| "maintenance_state": "ON", |
| "cpu_count": 1, |
| "total_mem": 2097152, |
| "disk_info": [{"size": "80000000", "mountpoint": "/"}], |
| } |
| }, |
| { |
| "Hosts": { |
| "host_name": "host2", |
| "maintenance_state": "ON", |
| "cpu_count": 1, |
| "total_mem": 2097152, |
| "disk_info": [{"size": "80000000", "mountpoint": "/"}], |
| } |
| }, |
| ] |
| } |
| |
| actualRecommendLayoutResponse = default_stack_advisor.recommendComponentLayout( |
| services, hosts |
| ) |
| |
| expectedRecommendLayoutResponse = { |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| "hosts": [], |
| "services": ["GANGLIA", "HBASE", "HDFS", "PIG", "TEZ", "ZOOKEEPER"], |
| "recommendations": { |
| "blueprint": {"host_groups": []}, |
| "blueprint_cluster_binding": {"host_groups": []}, |
| }, |
| } |
| |
| self.assertEqual(actualRecommendLayoutResponse, expectedRecommendLayoutResponse) |
| |
| # Config groups support by default |
| services["config-groups"] = [{"configurations": {}, "hosts": ["host2"]}] |
| |
| actualConfigGroupRecommendConfigResponse = ( |
| default_stack_advisor.recommendConfigurations(services, hosts) |
| ) |
| expectedConfigGroupRecommendConfigResponse = { |
| "Versions": {"stack_name": "HDP1", "stack_version": "2.0.6"}, |
| "hosts": ["host1", "host2"], |
| "services": ["GANGLIA", "HBASE", "HDFS", "PIG", "TEZ", "ZOOKEEPER"], |
| "recommendations": { |
| "config-groups": [ |
| {"configurations": {}, "dependent_configurations": {}, "hosts": ["host2"]} |
| ], |
| "blueprint": {"configurations": {}, "host_groups": []}, |
| "blueprint_cluster_binding": {"host_groups": []}, |
| }, |
| } |
| self.assertEqual( |
| actualConfigGroupRecommendConfigResponse, |
| expectedConfigGroupRecommendConfigResponse, |
| ) |
| |
| services = { |
| "services": [ |
| { |
| "StackServices": { |
| "service_name": "YARN", |
| "stack_name": "HDP", |
| "stack_version": "2.3", |
| }, |
| "configurations": [ |
| { |
| "StackConfigurations": { |
| "property_depended_by": [ |
| { |
| "type": "yarn-site", |
| "name": "yarn.scheduler.minimum-allocation-vcores", |
| }, |
| { |
| "type": "yarn-site", |
| "name": "yarn.scheduler.maximum-allocation-vcores", |
| }, |
| ], |
| "property_name": "yarn.nodemanager.resource.cpu-vcores", |
| "type": "yarn-site.xml", |
| }, |
| "dependencies": [], |
| }, |
| { |
| "StackConfigurations": { |
| "property_name": "yarn.nodemanager.resource.memory-mb", |
| "type": "yarn-site.xml", |
| }, |
| "dependencies": [ |
| { |
| "StackConfigurationDependency": { |
| "dependency_name": "yarn.scheduler.maximum-allocation-mb", |
| "dependency_type": "yarn-site", |
| } |
| }, |
| { |
| "StackConfigurationDependency": { |
| "dependency_name": "yarn.scheduler.minimum-allocation-mb", |
| "dependency_type": "yarn-site", |
| } |
| }, |
| ], |
| }, |
| { |
| "StackConfigurations": { |
| "property_depended_by": [ |
| {"type": "mapred-site", "name": "yarn.app.mapreduce.am.resource.mb"}, |
| {"type": "mapred-site", "name": "mapreduce.map.memory.mb"}, |
| {"type": "mapred-site", "name": "mapreduce.reduce.memory.mb"}, |
| ], |
| "property_name": "yarn.scheduler.maximum-allocation-mb", |
| "type": "yarn-site.xml", |
| }, |
| "dependencies": [], |
| }, |
| { |
| "StackConfigurations": { |
| "property_depended_by": [], |
| "property_name": "yarn.scheduler.maximum-allocation-vcores", |
| "type": "yarn-site.xml", |
| }, |
| "dependencies": [], |
| }, |
| { |
| "StackConfigurations": { |
| "property_name": "yarn.scheduler.minimum-allocation-mb", |
| "type": "yarn-site.xml", |
| }, |
| "dependencies": [ |
| { |
| "StackConfigurationDependency": { |
| "dependency_name": "hive.tez.container.size", |
| "dependency_type": "hive-site", |
| } |
| }, |
| { |
| "StackConfigurationDependency": { |
| "dependency_name": "yarn.app.mapreduce.am.resource.mb", |
| "dependency_type": "mapred-site", |
| } |
| }, |
| { |
| "StackConfigurationDependency": { |
| "dependency_name": "mapreduce.map.memory.mb", |
| "dependency_type": "mapred-site", |
| } |
| }, |
| { |
| "StackConfigurationDependency": { |
| "dependency_name": "mapreduce.reduce.memory.mb", |
| "dependency_type": "mapred-site", |
| } |
| }, |
| ], |
| }, |
| { |
| "StackConfigurations": { |
| "property_name": "yarn.scheduler.minimum-allocation-vcores", |
| "type": "yarn-site.xml", |
| }, |
| "dependencies": [], |
| }, |
| ], |
| } |
| ], |
| "changed-configurations": [ |
| {"type": "yarn-site", "name": "yarn.nodemanager.resource.memory-mb"} |
| ], |
| } |
| |
| properties_dict = default_stack_advisor.getAffectedConfigs(services) |
| expected_properties_dict = [ |
| {"name": "yarn.scheduler.maximum-allocation-mb", "type": "yarn-site"}, |
| {"name": "yarn.scheduler.minimum-allocation-mb", "type": "yarn-site"}, |
| {"name": "hive.tez.container.size", "type": "hive-site"}, |
| {"name": "yarn.app.mapreduce.am.resource.mb", "type": "mapred-site"}, |
| {"name": "mapreduce.map.memory.mb", "type": "mapred-site"}, |
| {"name": "mapreduce.reduce.memory.mb", "type": "mapred-site"}, |
| ] |
| |
| self.assertEqual(properties_dict, expected_properties_dict) |