source: old/trunk/vtest/nservers.py @ 2647

Revision 2647, 8.0 KB checked in by kcr, 5 months ago (diff)

add method for subcribing to many classes at once

Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# Copyright © 2009 by Karl Ramm
4#
5# All rights reserved.
6#
7# Permission to use, copy, modify, and distribute this software and
8# its documentation for any purpose and without fee is hereby granted,
9# provided that the above copyright notice appear in all copies and
10# that both that copyright notice and this permission notice appear in
11# supporting documentation, and that the name of Karl Ramm not be used
12# in advertising or publicity pertaining to distribution of the
13# software without specific, written prior permission.
14#
15# KARL RAMM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17# NO EVENT SHALL KARL RAMM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23import sys
24import os
25import time
26import traceback
27import logging
28import errno
29import subprocess
30import fcntl
31import itertools
32
33
34import cluster
35import ztest
36
37class BaseTest(object):
38    def __init__(self):
39        self.log = logging.getLogger(self.__class__.__name__)
40    def setup(self):
41        self.log.info('starting setup')
42    def teardown(self):
43        self.log.info('starting teardown')
44    def test(self):
45        self.log.info('starting test')
46    def run(self):
47        failed = False
48        try:
49            self.setup()
50        except:
51            self.handle(sys.exc_info())
52            failed = 'setup'
53        if not failed:
54            try:
55                self.test()
56            except:
57                self.handle(sys.exc_info())
58                failed = 'test'
59        try:
60            self.teardown()
61        except:
62            self.handle(sys.exc_info())
63            if not failed:
64                failed = 'teardown'
65        if not failed:
66            self.log.info('success')
67        else:
68            self.log.error(failed + ' failed')
69            sys.exit(1)
70
71    def handle(self, failure):
72        self.log.error('exception:', exc_info=failure)
73        if '--no-wait' not in sys.argv:
74            print 'waiting for acknowledgement'
75            raw_input()
76
77class TestMultipleServers(BaseTest):
78    def setup(self):
79        super(TestMultipleServers, self).setup()
80
81        self.nservers = 3
82
83        self.cluster = cluster.cluster(spec=[ztest.kdc] + [cluster.host]*(self.nservers+1)) # client + n servers
84        self.cluster.setup()
85
86        self.hosts = [testmachine for (testmachine, prototype) in self.cluster.machines[cluster.host]]
87        self.servers = self.hosts[1:]
88        self.client = self.hosts[0]
89        self.kdc = self.cluster.machines[ztest.kdc][0][1]
90
91        for h in self.hosts:
92            h.putstr('/etc/krb5.conf', self.kdc.krb5_conf)
93            h.script('mkdir /etc/zephyr')
94            h.putstr('/etc/zephyr/server.list', '\n'.join(t.params['hostname'] for t in self.servers) + '\n')
95
96        ktname = self.kdc.keytab('zephyr/zephyr')
97
98        for t in self.servers:
99            t.putstr('/etc/rsyslog.d/zephyrlog.conf', 'local6.* /var/log/zephyr.log\n')
100            t.script('/etc/init.d/rsyslog restart')
101            t.putfile(ktname, '/etc/zephyr/krb5.keytab')
102            t.script('touch /etc/zephyr/srvtab') # sigh, packaging bug
103
104        #XXX need to cons up an apt repository
105        packagepath = '/home/kcr/src'
106        packageversion = '3.0.1~rc.HEAD'
107        arch = 'i386'
108        serverpackages = ['libzephyr4-krb5', 'zephyr-server-krb5', 'zephyr-clients']
109        clientpackages = ['libzephyr4-krb5', 'zephyr-clients']
110        serverdebs = [package + '_' + packageversion + '_' + arch + '.deb'
111                      for package in serverpackages]
112        clientdebs = [package + '_' + packageversion + '_' + arch + '.deb'
113                      for package in clientpackages]
114
115        for t in self.servers:
116            for deb in serverdebs:
117                t.putfile(os.path.join(packagepath, deb), '/tmp')
118                t.script('DEBIAN_FRONTEND=noninteractive dpkg -i ' + os.path.join('/tmp', deb))
119        time.sleep(1) # let things settle
120
121        for deb in clientdebs:
122            self.client.putfile(os.path.join(packagepath, deb), '/tmp')
123            self.client.script('DEBIAN_FRONTEND=noninteractive dpkg -i ' + os.path.join('/tmp', deb))
124
125        self.serverwait(30)
126    def test(self):
127        super(TestMultipleServers, self).test()
128        self.verify_client()
129
130    def teardown(self):
131        super(TestMultipleServers, self).teardown()
132        if self.servers:
133            for t in self.servers:
134                if t.alive:
135                    t.getfile('/var/log/zephyr.log', t.params['hostname'] + '.zephyr.log')
136        self.cluster.teardown()
137
138    def verify_client(self):
139        self.client.script(['echo test2 | kinit test2',
140                       'zwgc -ttymode > /tmp/zwgcout',
141                       'zwrite test2 -m FROTNITZ',
142                       'zctl wg_exit',])
143
144        ret, stdout, stderr = self.client.run('cat /tmp/zwgcout')
145
146        assert 'FROTNITZ' in stdout, 'not receiving zephyrgrams'
147        assert 'Authentic' in stdout, 'zephyrgram not authentic'
148
149        ret, stdout, stderr = self.client.run('ps gax | grep -v grep | grep zwgc')
150
151        assert 'zwgc' not in stdout, 'zwgc still running'
152
153    def serverwait(self, delay=120):
154        for i in range(delay / 5):
155            time.sleep(5)
156            ret, stdout, stderr = self.client.run('zstat')
157            if stdout.count('SERV_UP') == self.nservers:
158                break
159            self.log.info('servers not up yet')
160        else:
161            assert False, 'server failed to restart in a timely fashion'
162
163
164    class Zwgc(object):
165        def __init__(self, other):
166            self.counter = itertools.count().next
167            self.client = other.client
168            self.log = other.log
169            self.nservers = other.nservers
170            self.wgfile = '/tmp/wg.test.%d' % self.counter()
171            self.z = subprocess.Popen(self.client.params['ssh'].split() +
172                                      ['env', 'WGFILE=' + self.wgfile, 'zwgc', '-ttymode', '-nofork'],
173                                      stdin=open('/dev/null'), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
174            fcntl.fcntl(self.z.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
175            fcntl.fcntl(self.z.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
176            time.sleep(1)
177        def read(self):
178            try:
179                return self.z.stdout.read()
180            except IOError, e:
181                if e.errno != errno.EAGAIN:
182                    raise
183                return None
184        def receivetest(self):
185            for i in xrange(self.nservers+1):
186                message = 'foobly%d' % self.counter()
187                self.client.script('zwrite test2 -m '+message)
188                time.sleep(.25)
189                received = self.read()
190                self.log.info('received %s', repr(received))
191                assert message in received
192                self.client.run('zctl new_server')
193                time.sleep(.5)
194        def ret(self):
195            'not robust'
196            retval, stdout, stderr = self.client.run('env WGFILE=%s zctl ret' % self.wgfile)
197            return [tuple(l.split(' ')[1::2]) for l in stdout.splitlines()]
198        def sub(self, class_, instance='*', recipient='*'):
199            self.client.script('env WGFILE=%s zctl sub %s %s %s' %
200                               (self.wgfile, class_, instance, recipient))
201            return (class_, instance, recipient) in self.ret()
202        def subclasses(self, classlist):
203            self.client.putstr('/tmp/subs', ''.join('%s,*,*\n' % (class_,) for class_ in classlist))
204            self.client.script('env WGFILE=%s zctl load /tmp/subs' % (self.wgfile,))
205        def shutdown(self):
206            self.client.script('env WGFILE=%s zctl wg_exit' % self.wgfile)
207    def zwgc(self):
208        return self.Zwgc(self)
209
210if __name__ == '__main__':
211    TestMultipleServers().run()
Note: See TracBrowser for help on using the repository browser.