~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/testing/fixture.py

  • Committer: Stuart Bishop
  • Date: 2011-09-05 15:42:27 UTC
  • mto: (13813.4.4 pgbouncer-fixture)
  • mto: This revision was merged to the branch mainline in revision 13875.
  • Revision ID: stuart.bishop@canonical.com-20110905154227-ke7d9fy9jr9uk87y
Revert reversion in launchpad/devel r13865

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
    'ZopeViewReplacementFixture',
12
12
    ]
13
13
 
 
14
from ConfigParser import SafeConfigParser
 
15
import os.path
14
16
from textwrap import dedent
15
17
 
16
 
from fixtures import Fixture
 
18
from fixtures import (
 
19
    EnvironmentVariableFixture,
 
20
    Fixture,
 
21
    )
 
22
import pgbouncer.fixture
17
23
import rabbitfixture.server
18
24
from zope.component import (
19
25
    getGlobalSiteManager,
27
33
    undefineChecker,
28
34
    )
29
35
 
 
36
from canonical.config import config
 
37
 
30
38
 
31
39
class RabbitServer(rabbitfixture.server.RabbitServer):
32
40
    """A RabbitMQ server fixture with Launchpad-specific config.
46
54
            """ % self.config.port)
47
55
 
48
56
 
 
57
class PGBouncerFixture(pgbouncer.fixture.PGBouncerFixture):
 
58
    """Inserts a controllable pgbouncer instance in front of PostgreSQL.
 
59
 
 
60
    The pgbouncer proxy can be shutdown and restarted at will, simulating
 
61
    database outages and fastdowntime deployments.
 
62
    """
 
63
 
 
64
    def __init__(self):
 
65
        super(PGBouncerFixture, self).__init__()
 
66
 
 
67
        # Known databases
 
68
        from canonical.testing.layers import DatabaseLayer
 
69
        dbnames = [
 
70
            DatabaseLayer._db_fixture.dbname,
 
71
            DatabaseLayer._db_template_fixture.dbname,
 
72
            'session_ftest',
 
73
            'launchpad_empty',
 
74
            ]
 
75
        for dbname in dbnames:
 
76
            self.databases[dbname] = 'dbname=%s port=5432 host=localhost' % (
 
77
                dbname,)
 
78
 
 
79
        # Known users, pulled from security.cfg
 
80
        security_cfg_path = os.path.join(
 
81
            config.root, 'database', 'schema', 'security.cfg')
 
82
        security_cfg_config = SafeConfigParser({})
 
83
        security_cfg_config.read([security_cfg_path])
 
84
        for section_name in security_cfg_config.sections():
 
85
            self.users[section_name] = 'trusted'
 
86
            self.users[section_name + '_ro'] = 'trusted'
 
87
        self.users[os.environ['USER']] = 'trusted'
 
88
 
 
89
    def setUp(self):
 
90
        super(PGBouncerFixture, self).setUp()
 
91
 
 
92
        # reconnect_store cleanup added first so it is run last, after
 
93
        # the environment variables have been reset.
 
94
        self.addCleanup(self._maybe_reconnect_stores)
 
95
 
 
96
        # Abuse the PGPORT environment variable to get things connecting
 
97
        # via pgbouncer. Otherwise, we would need to temporarily
 
98
        # overwrite the database connection strings in the config.
 
99
        self.useFixture(EnvironmentVariableFixture('PGPORT', str(self.port)))
 
100
 
 
101
        # Reset database connections so they go through pgbouncer.
 
102
        self._maybe_reconnect_stores()
 
103
 
 
104
    def _maybe_reconnect_stores(self):
 
105
        """Force Storm Stores to reconnect if they are registered.
 
106
 
 
107
        This is a noop if the Component Architecture is not loaded,
 
108
        as we are using a test layer that doesn't provide database
 
109
        connections.
 
110
        """
 
111
        from canonical.testing.layers import (
 
112
            reconnect_stores,
 
113
            is_ca_available,
 
114
            )
 
115
        if is_ca_available():
 
116
            reconnect_stores()
 
117
 
 
118
 
49
119
class ZopeAdapterFixture(Fixture):
50
120
    """A fixture to register and unregister an adapter."""
51
121