create reserved group for all hosts

- temporarily create a reserved group for all hosts. this is needed when you
want to run an ansible command against a host that might not yet be in a group.
This is used for host check and setup. Oracle-Bug:21824287
- handle case when empty inventory has whitespace in it. useful when manually
clearing the inventory file
- add rule preventing adding a group name equal to an existing service name.
Oracle-bug:21831776
- add exception handling to run_cmd to better output cmd failures when an
exception occurs.
- add restriction to avoid pexpect 3.3 in requirements. That version has a
bug where it will fail sudo commands.
- change unittest kolla_cli etc location to be the user's home location. This
avoids errors when the kolla_cli location is in /etc/kolla
- change format of unittest test_hosts file to remove ip address. no longer
needed.
- remove ndbcluster from group test
This commit is contained in:
steve 2015-09-14 15:35:35 -04:00 committed by Steve Noyes
parent 37877e6aa8
commit 2f38d3342d
5 changed files with 65 additions and 40 deletions

View File

@ -283,7 +283,7 @@ class Inventory(object):
with open(inventory_path, 'rb') as inv_file:
data = inv_file.read()
if data:
if data.strip():
inventory = jsonpickle.decode(data)
# upgrade version handling
@ -380,11 +380,15 @@ class Inventory(object):
# create new host if it doesn't exist
host = Host(hostname)
if not groupname:
if hostname not in self.get_hostnames():
# a new host is being added to the inventory
self._hosts[hostname] = host
else:
# a host is to be added to an existing group
elif groupname:
group = self._groups[groupname]
group.add_host(host)
if hostname not in group.get_hostnames():
group.add_host(host)
def remove_host(self, hostname, groupname=None):
"""remove host
@ -409,6 +413,12 @@ class Inventory(object):
del self._hosts[hostname]
def add_group(self, groupname):
# Group names cannot overlap with service names:
if groupname in SERVICE_GROUPS:
raise CommandError('ERROR: Invalid group name. A service name '
'cannot be used for a group name.')
if groupname not in self._groups:
self._groups[groupname] = HostGroup(groupname)
@ -430,19 +440,20 @@ class Inventory(object):
if hosts is none, return all groups in inventory
"""
if not host:
return self._groups.values()
groups = []
for group in self._groups.values():
if host.name in group.get_hostnames():
groups.append(group)
if not host:
groups = self._groups.values()
else:
for group in self._groups.values():
if host.name in group.get_hostnames():
groups.append(group)
return groups
def get_group_services(self):
"""return { groupname : [servicenames] }"""
group_services = {}
for group in self._groups.values():
for group in self.get_groups():
group_services[group.name] = []
for service in group.services:
group_services[group.name].append(service.name)
@ -451,7 +462,7 @@ class Inventory(object):
def get_group_hosts(self):
"""return { groupname : [hostnames] }"""
group_hosts = {}
for group in self._groups.values():
for group in self.get_groups():
group_hosts[group.name] = []
for host in group.get_hosts():
group_hosts[group.name].append(host.name)
@ -500,7 +511,7 @@ class Inventory(object):
'hosts exist')
self.remote_mode = remote_flag
for group in self._groups.values():
for group in self.get_groups():
group.set_remote(remote_flag)
def get_ansible_json(self):
@ -560,6 +571,14 @@ class Inventory(object):
jdict[containername]['children'] = [service.name]
jdict[containername]['vars'] = {}
# temporaily create group containing all hosts. this is needed for
# ansible commands that are performed on hosts not yet in groups.
group = self.add_group('__RESERVED__')
jdict[group.name] = {}
jdict[group.name]['hosts'] = self.get_hostnames()
jdict[group.name]['vars'] = group.get_vars()
self.remove_group(group.name)
# process hosts vars
jdict['_meta'] = {}
jdict['_meta']['hostvars'] = {}

View File

@ -84,16 +84,20 @@ def convert_to_unicode(the_string):
def run_cmd(cmd, print_output=True):
log = logging.getLogger(__name__)
err_flag = False
child = pexpect.spawn(cmd)
child.maxsize = 1
child.timeout = 86400
output = []
for line in child:
outline = line.rstrip()
output.append(outline)
if print_output:
log.info(outline)
child.close()
if child.exitstatus != 0:
try:
child = pexpect.spawn(cmd)
child.maxsize = 1
child.timeout = 86400
for line in child:
outline = line.rstrip()
output.append(outline)
if print_output:
log.info(outline)
child.close()
if child.exitstatus != 0:
err_flag = True
except Exception as e:
err_flag = True
return err_flag, '\n'.join(output)
output.append('%s' % e)
return err_flag, output

View File

@ -7,6 +7,6 @@ jsonpickle>=0.9
oslo.i18n>=1.3.0 # Apache-2.0
paramiko>=1.15
pbr>=0.10
pexpect>=2.3
pexpect>=2.3,<3.3
PyYAML>=3.10
six>=1.9.0
six>=1.9.0

View File

@ -33,6 +33,7 @@ HOSTS_FNAME = 'test_hosts'
class KollaCliTest(testtools.TestCase):
saved_kolla_etc = ''
cmd_prefix = ''
log = logging.getLogger(__name__)
@ -73,16 +74,12 @@ class KollaCliTest(testtools.TestCase):
# PRIVATE FUNCTIONS ----------------------------------------------------
def _setup_env_var(self):
etc_path = utils.get_kollacli_etc()
if not etc_path.endswith(TEST_SUFFIX):
etc_path = os.path.join(etc_path, TEST_SUFFIX)
os.environ[ENV_ETC] = etc_path
"""set kolla etc to user's home directory"""
self.saved_kolla_etc = utils.get_kollacli_etc()
os.environ[ENV_ETC] = os.path.expanduser('~')
def _restore_env_var(self):
etc_path = utils.get_kollacli_etc()
if etc_path.endswith(TEST_SUFFIX):
etc_path = etc_path.rsplit('/', 1)[0]
os.environ[ENV_ETC] = etc_path
os.environ[ENV_ETC] = self.saved_kolla_etc
def _run_command(self, cmd):
# self.log.debug('run cmd: %s' % cmd)
@ -207,7 +204,12 @@ class TestHosts(object):
return self.info[name]['pwd']
def load(self):
"""load hosts from test_hosts file"""
"""load hosts from test_hosts file
format of file is:
hostname1 password1
hostname2 password2
"""
path = self.get_test_hosts_path()
with open(path, 'r') as f:
for line in f:
@ -216,11 +218,11 @@ class TestHosts(object):
continue
tokens = line.split()
if len(tokens) != 3:
raise Exception('%s expected 3 params on line: %s'
if len(tokens) != 2:
raise Exception('%s expected 2 params on line: %s'
% (HOSTS_FNAME, line))
hostname = tokens[0]
pwd = tokens[2]
pwd = tokens[1]
self.add(hostname)
self.set_password(hostname, pwd)

View File

@ -134,7 +134,7 @@ class TestFunctional(KollaCliTest):
groupname = group['Group']
services = group['Services']
service1 = 'ndbcluster'
service1 = 'mysql'
service2 = 'rabbitmq'
services.append(service1)
@ -167,7 +167,7 @@ class TestFunctional(KollaCliTest):
group listservices -f json:
[{"Group Name": "compute", "Services": []},
{"Group Name": "control",
"Services": ["glance", "keystone", "ndbcluster",
"Services": ["glance", "keystone", "mysql",
"nova", "rabbitmq"]},
{"Group Name": "network", "Services": ["haproxy", "neutron"]}]
"""