The test suite local client now properly receives the events. Fixes #3214.

* We were instantiating the integration testing local client too soon in the process. Deferring it to a little latter made it all work.
* Added the ability to dump the master and minion testing configurations to files. Just prepend the `runtests` call with `DUMP_SALT_CONFIG=1` and you'll get the computed configuration files in `/tmp/salttest/{master,minion}`.
* We now also un-subscribe from the event's once done.
* Added `salt.utils.event.LocalClientEvent` just to differentiate from `salt.utils.event.MasterEvent` in the logs so we know who's who. It's just a subclass of the latter.
This commit is contained in:
Pedro Algarvio 2013-01-11 16:21:04 +00:00
parent eacd67e902
commit 39f03c59cd
3 changed files with 62 additions and 34 deletions

View File

@ -77,7 +77,7 @@ class LocalClient(object):
self.serial = salt.payload.Serial(self.opts)
self.salt_user = self.__get_user()
self.key = self.__read_master_key()
self.event = salt.utils.event.MasterEvent(self.opts['sock_dir'])
self.event = salt.utils.event.LocalClientEvent(self.opts['sock_dir'])
def __read_master_key(self):
'''
@ -163,9 +163,10 @@ class LocalClient(object):
Common checks on the pub_data data structure returned from running pub
'''
if not pub_data:
err = ('Failed to authenticate, is this user permitted to execute '
'commands?')
raise EauthAuthenticationError(err)
raise EauthAuthenticationError(
'Failed to authenticate, is this user permitted to execute '
'commands?'
)
# Failed to connect to the master and send the pub
if not 'jid' in pub_data or pub_data['jid'] == '0':

View File

@ -130,18 +130,21 @@ class SaltEvent(object):
if not self.cpub:
self.connect_pub()
self.sub.setsockopt(zmq.SUBSCRIBE, tag)
while True:
socks = dict(self.poller.poll(wait))
if self.sub in socks and socks[self.sub] == zmq.POLLIN:
raw = self.sub.recv()
data = self.serial.loads(raw[20:])
if full:
ret = {'data': data,
'tag': raw[:20].rstrip('|')}
return ret
return data
else:
try:
while True:
socks = dict(self.poller.poll(wait))
if self.sub in socks and socks[self.sub] == zmq.POLLIN:
raw = self.sub.recv()
data = self.serial.loads(raw[20:])
if full:
ret = {'data': data,
'tag': raw[:20].rstrip('|')}
return ret
return data
return None
finally:
# No sense in keeping subscribed to this event
self.sub.setsockopt(zmq.UNSUBSCRIBE, tag)
def iter_events(self, tag='', full=False):
'''
@ -202,6 +205,13 @@ class MasterEvent(SaltEvent):
self.connect_pub()
class LocalClientEvent(MasterEvent):
'''
This class is just used to differentiate who is handling the events,
specially on logs, but it's the same as MasterEvent.
'''
class MinionEvent(SaltEvent):
'''
Create a master event management object

View File

@ -239,25 +239,28 @@ class TestDaemon(object):
self.syndic_process = multiprocessing.Process(target=syndic.tune_in)
self.syndic_process.start()
#if os.environ.get('DUMP_SALT_CONFIG', None) is not None:
# try:
# import yaml
# os.makedirs('/tmp/salttest/conf')
# except OSError:
# pass
# self.master_opts['user'] = pwd.getpwuid(os.getuid()).pw_name
# self.minion_opts['user'] = pwd.getpwuid(os.getuid()).pw_name
# open('/tmp/salttest/conf/master', 'w').write(
# yaml.dump(self.master_opts)
# )
# open('/tmp/salttest/conf/minion', 'w').write(
# yaml.dump(self.minion_opts)
# )
if os.environ.get('DUMP_SALT_CONFIG', None) is not None:
from copy import deepcopy
try:
import yaml
os.makedirs('/tmp/salttest/conf')
except OSError:
pass
master_opts = deepcopy(self.master_opts)
minion_opts = deepcopy(self.minion_opts)
master_opts.pop('conf_file', None)
master_opts['user'] = pwd.getpwuid(os.getuid()).pw_name
# Let's create a local client to ping and sync minions
self.client = salt.client.LocalClient(
os.path.join(INTEGRATION_TEST_DIR, 'files', 'conf', 'master')
)
minion_opts['user'] = pwd.getpwuid(os.getuid()).pw_name
minion_opts.pop('conf_file', None)
minion_opts.pop('grains', None)
minion_opts.pop('pillar', None)
open('/tmp/salttest/conf/master', 'w').write(
yaml.dump(master_opts)
)
open('/tmp/salttest/conf/minion', 'w').write(
yaml.dump(minion_opts)
)
self.minion_targets = set(['minion', 'sub_minion'])
self.pre_setup_minions()
@ -282,6 +285,20 @@ class TestDaemon(object):
finally:
self.post_setup_minions()
@property
def client(self):
'''
Return a local client which will be used for example to ping and sync
the test minions.
This client is defined as a class attribute because it's creation needs
to be deferred to a latter stage. If created it on `__enter__` like it
previously was, it would not receive the master events.
'''
return salt.client.LocalClient(
mopts=self.master_opts
)
def __exit__(self, type, value, traceback):
'''
Kill the minion and master processes
@ -470,7 +487,7 @@ class TestDaemon(object):
sys.stdout.flush()
responses = self.client.cmd(
','.join(expected_connections), 'test.ping', expr_form='list',
list(expected_connections), 'test.ping', expr_form='list',
)
for target in responses:
if target not in expected_connections: