diff --git a/kollacli/common/ansible/actions.py b/kollacli/common/ansible/actions.py index a07f3b2..ccf9eb6 100644 --- a/kollacli/common/ansible/actions.py +++ b/kollacli/common/ansible/actions.py @@ -17,11 +17,13 @@ import os import kollacli.i18n as u from kollacli.common.ansible.playbook import AnsiblePlaybook +from kollacli.common.inventory import Inventory from kollacli.common import properties from kollacli.common.properties import AnsibleProperties from kollacli.common.utils import get_kolla_etc from kollacli.common.utils import get_kolla_home from kollacli.common.utils import get_kollacli_home +from kollacli.common.utils import is_string_true from kollacli.exceptions import CommandError LOG = logging.getLogger(__name__) @@ -116,14 +118,45 @@ def upgrade(verbose_level=1): def _run_deploy_rules(): + properties = AnsibleProperties() + inventory = Inventory.load() + # check that every group with enabled services + # has hosts associated to it + group_services = inventory.get_group_services() + failed_groups = [] + failed_services = [] + if group_services: + for (groupname, servicenames) in group_services.items(): + group = inventory.get_group(groupname) + hosts = group.get_hostnames() + + group_needs_host = False + if not hosts: + for service in servicenames: + # check service enablement + enabled_property = 'enable_' + service.replace('-', '_') + is_enabled = properties.get_property(enabled_property) + if is_string_true(is_enabled): + group_needs_host = True + failed_services.append(service) + if group_needs_host: + failed_groups.append(groupname) + + if len(failed_groups) > 0: + raise CommandError( + u._('Deploy failed. ' + 'Groups: {groups} with enabled ' + 'services : {services} ' + 'have no associated hosts') + .format(groups=failed_groups, services=failed_services)) + # check that ring files are in /etc/kolla/config/swift if # swift is enabled expected_files = ['account.ring.gz', 'container.ring.gz', 'object.ring.gz'] - properties = AnsibleProperties() is_enabled = properties.get_property('enable_swift') - if is_enabled == 'yes': + if is_string_true(is_enabled): path_pre = os.path.join(get_kolla_etc(), 'config', 'swift') for expected_file in expected_files: path = os.path.join(path_pre, expected_file) diff --git a/kollacli/common/inventory.py b/kollacli/common/inventory.py index 0c1979f..80eaf66 100644 --- a/kollacli/common/inventory.py +++ b/kollacli/common/inventory.py @@ -717,7 +717,7 @@ class Inventory(object): return svc_sub_svcs def get_service_groups(self): - """set services and their groups + """get services and their groups return { servicename: ([groupnames], inherit=True/False/None) } """ diff --git a/kollacli/common/utils.py b/kollacli/common/utils.py index bf12505..f47d475 100644 --- a/kollacli/common/utils.py +++ b/kollacli/common/utils.py @@ -273,3 +273,12 @@ def safe_decode(text): # py3 will raise if text is already a string pass return text + + +def is_string_true(string): + """Return boolean True if string represents a true value (None is False)""" + true_values = ['yes', 'true'] + if string is not None and string.lower() in true_values: + return True + else: + return False diff --git a/tests/common.py b/tests/common.py index cfb2a0c..c8398ef 100644 --- a/tests/common.py +++ b/tests/common.py @@ -31,6 +31,29 @@ KOLLA_SHELL_DIR = 'kollacli' CFG_FNAME = 'test_config.yml' +ALL_SERVICES = [ + 'ceilometer', 'cinder', 'cinder_backup', 'cinder_volume', + 'glance', 'haproxy', 'heat', 'memcached', 'mysqlcluster', + 'mysqlcluster_ndb', 'horizon', 'keystone', 'murano', + 'neutron', 'neutron_server', 'nova', 'rabbitmq', + 'swift_container_server', 'swift_object_server' + ] +DISABLED_SERVICES = [ + 'ceilometer', 'cinder', 'cinder_backup', 'cinder_volume', + 'glance', 'haproxy', 'heat', 'memcached', 'mysqlcluster', + 'mysqlcluster_ndb', 'horizon', 'keystone', 'murano', + 'neutron', 'neutron_server', 'nova', + 'swift_container_server', 'swift_object_server' + ] +ENABLED_SERVICES = [ + 'rabbitmq' + ] +ENABLED_DATA_SERVICES = [ + 'rabbitmq_data' + ] + +UNKNOWN_HOST = 'Name or service not known' + class KollaCliTest(testtools.TestCase): diff --git a/tests/deploy.py b/tests/deploy.py index e95b0b0..24dd1af 100644 --- a/tests/deploy.py +++ b/tests/deploy.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. # +from common import ALL_SERVICES from common import KollaCliTest from kollacli.common.inventory import Inventory @@ -131,10 +132,18 @@ class TestFunctional(KollaCliTest): def test_deploy(self): # test will start with no hosts in the inventory # deploy will throw an exception if it fails + # disable all services first as without it empty groups cause errors + for service in ALL_SERVICES: + self.run_cli_cmd('property set enable_%s no' % service) + self.run_cli_cmd('deploy') self.run_cli_cmd('deploy --serial') self.run_cli_cmd('deploy --groups=control') + # re-enable services after the test + for service in ALL_SERVICES: + self.run_cli_cmd('property set enable_%s yes' % service) + def check_json(self, msg, groups, hosts, included_groups, included_hosts): err_msg = ('included groups: %s\n' % included_groups + 'included hosts: %s\n' % included_hosts) diff --git a/tests/destroy.py b/tests/destroy.py index 45cc69d..2e081f3 100644 --- a/tests/destroy.py +++ b/tests/destroy.py @@ -12,23 +12,16 @@ # License for the specific language governing permissions and limitations # under the License. # +from common import DISABLED_SERVICES +from common import ENABLED_DATA_SERVICES +from common import ENABLED_SERVICES from common import KollaCliTest from common import TestConfig +from common import UNKNOWN_HOST import unittest -DISABLED_SERVICES = [ - 'ceilometer', 'cinder', 'glance', 'haproxy', 'heat', 'msqlcluster', - 'horizon', 'keystone', 'murano', 'neutron', 'nova', - ] -ENABLED_SERVICES = [ - 'rabbitmq' - ] -ENABLED_DATA_SERVICES = [ - 'rabbitmq_data' - ] - -UNKNOWN_HOST = 'Name or service not known' +TEST_GROUP_NAME = 'test_group' class TestFunctional(KollaCliTest): @@ -62,11 +55,16 @@ class TestFunctional(KollaCliTest): 'Unexpected exception in host setup: %s' % e) # add host to a new deploy group - group_name = 'test_group' - self.run_cli_cmd('group add %s' % group_name) - self.run_cli_cmd('group addhost %s %s' % (group_name, hostname)) + self.run_cli_cmd('group add %s' % TEST_GROUP_NAME) + self.run_cli_cmd('group addhost %s %s' % (TEST_GROUP_NAME, hostname)) + # due to required host to group association where there are enabled + # services and we have only one host, move the enabled services + # out of control over to the new group, then move them back to + # control once we are done for service in ENABLED_SERVICES: - self.run_cli_cmd('service addgroup %s %s' % (service, group_name)) + self.run_cli_cmd('service removegroup %s control' % service) + self.run_cli_cmd('service addgroup %s %s' % + (service, TEST_GROUP_NAME)) # destroy services, initialize server try: @@ -166,6 +164,12 @@ class TestFunctional(KollaCliTest): for disabled_service in DISABLED_SERVICES: self.run_cli_cmd('property set enable_%s yes' % disabled_service) + # control once we are done + for service in ENABLED_SERVICES: + self.run_cli_cmd('service removegroup %s %s' % + (service, TEST_GROUP_NAME)) + self.run_cli_cmd('service addgroup %s control' % service) + super(KollaCliTest, self).tearDown()