[Checkins] SVN: gocept.zeoraid/trunk/src/gocept/zeoraid/ Reloading now uses the config file obtained from ZEO. This means that running
Thomas Lotze
tl at gocept.com
Thu Jan 8 06:57:09 EST 2009
Log message for revision 94616:
Reloading now uses the config file obtained from ZEO. This means that running
the RAID storage within a ZEO server is required for reloading the config.
Changed:
U gocept.zeoraid/trunk/src/gocept/zeoraid/datatypes.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/interfaces.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
-=-
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/datatypes.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/datatypes.py 2009-01-08 10:12:47 UTC (rev 94615)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/datatypes.py 2009-01-08 11:57:09 UTC (rev 94616)
@@ -14,6 +14,8 @@
"""ZConfig storage type definitions.
"""
+import inspect
+
import ZODB.config
import gocept.zeoraid.storage
@@ -21,9 +23,17 @@
class Storage(ZODB.config.BaseConfig):
def open(self):
+ parent_frame = inspect.stack()[1][0]
+ parent_self = parent_frame.f_locals.get('self')
+ if parent_self and parent_self.__class__.__name__ == 'ZEOServer':
+ zeo = parent_self
+ else:
+ zeo = None
+
return gocept.zeoraid.storage.RAIDStorage(
self.name,
self.config.storages,
blob_dir=self.config.blob_dir,
read_only=self.config.read_only,
- shared_blob_dir=self.config.shared_blob_dir)
+ shared_blob_dir=self.config.shared_blob_dir,
+ zeo=zeo)
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/interfaces.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/interfaces.py 2009-01-08 10:12:47 UTC (rev 94615)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/interfaces.py 2009-01-08 11:57:09 UTC (rev 94616)
@@ -42,7 +42,10 @@
def raid_recover(name):
pass
+ def raid_reload():
+ pass
+
class ITransactionInspection(zope.interface.Interface):
"""Storage API extension to allow inspecting historical transactions."""
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2009-01-08 10:12:47 UTC (rev 94615)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2009-01-08 11:57:09 UTC (rev 94616)
@@ -120,10 +120,11 @@
timeout = 60
def __init__(self, name, openers, read_only=False, blob_dir=None,
- shared_blob_dir=False):
+ shared_blob_dir=False, zeo=None):
self.__name__ = name
self.read_only = read_only
self.shared_blob_dir = shared_blob_dir
+ self.zeo = zeo
self.storages = {}
self._threads = set()
# Temporary files and directories that should be removed at the end of
@@ -595,13 +596,18 @@
return 'recovering %r' % (name,)
@ensure_open_storage
- def raid_reload(self, path):
- s = ""
+ def raid_reload(self):
+ if not self.zeo:
+ raise RuntimeError(
+ 'Cannot reload config without running inside ZEO.')
+
options = ZEOOptions()
- options.realize(['-C',path])
+ options.realize(['-C', self.zeo.options.configfile])
new_storages = dict([(o.name,o) for o in options.storages[0].config.storages])
storages_to_add = [(name, opener) for name, opener in new_storages.items() if name not in self.openers]
storages_to_remove = [(name, opener) for name, opener in self.openers.items() if name not in new_storages]
+
+ s = ""
for name, opener in storages_to_remove:
self.raid_disable(name)
s += "removed %s\n" % name
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py 2009-01-08 10:12:47 UTC (rev 94615)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_basics.py 2009-01-08 11:57:09 UTC (rev 94616)
@@ -42,6 +42,7 @@
from ZEO.ClientStorage import ClientStorage
from ZEO.tests import forker, CommitLockTests, ThreadTests
from ZEO.tests.testZEO import get_port
+import ZEO.runzeo
import ZODB.interfaces
import ZEO.interfaces
@@ -1239,7 +1240,10 @@
self._storage.tpc_begin(t)
self.assertEquals('degraded', self._storage.raid_status())
+ def test_reload_without_zeo(self):
+ self.assertRaises(RuntimeError, self._storage.raid_reload)
+
class FailingStorageTests(FailingStorageTestBase,
FailingStorageTestSetup):
@@ -1455,7 +1459,18 @@
class ExtensionMethodsTests(ZEOStorageBackendTests):
- def saveConfig(self, storages):
+ def open(self):
+ self.zeo_configfile = tempfile.mktemp()
+ self._server_storage_files.append(self.zeo_configfile)
+ self.update_config()
+
+ options = ZEO.runzeo.ZEOOptions()
+ options.realize(['-C', self.zeo_configfile])
+ zeo = ZEO.runzeo.ZEOServer(options)
+ zeo.open_storages()
+ self._storage = zeo.storages['teststorage']
+
+ def update_config(self):
# create a config file and save it
file_contents = """\
%%import gocept.zeoraid
@@ -1463,10 +1478,10 @@
address 127.0.0.1:%s
</zeo>
- <raidstorage main>
+ <raidstorage teststorage>
""" % get_port()
- for count, storage in enumerate(storages):
+ for count, storage in enumerate(self._storages):
file_contents += """\
<zeoclient %s>
server %s:%s
@@ -1479,15 +1494,15 @@
</raidstorage>
"""
- filename = tempfile.mktemp()
- self._server_storage_files = [ ]
- self._server_storage_files.append(filename)
- f = open(filename, 'w')
+ f = open(self.zeo_configfile, 'w')
f.write(file_contents)
f.close()
- return filename
def test_reload_add(self):
+ self.assertEquals(len(self._storage.openers), 5)
+ self.assertEquals([], self._storage.storages_degraded)
+
+ # set up a new backend
port = get_port()
zconf = forker.ZEOConfig(('', port))
zport, adminaddr, pid, path = forker.start_zeo_server(self.getConfig(),
@@ -1498,40 +1513,45 @@
min_disconnect_poll=0.5, wait=1,
wait_timeout=60))
- filename = self.saveConfig(self._storages)
+ # configure the RAID to use the new backend
+ self.update_config()
+ self._storage.raid_reload()
- self.assertEquals(len(self._storage.openers), 5)
- self.assertEquals([], self._storage.storages_degraded)
- self._storage.raid_reload(filename)
self.assertEquals(len(self._storage.openers), 6)
self.assertEquals(['5'], self._storage.storages_degraded)
+ # ensure that we can still write to the RAID
oid = self._storage.new_oid()
self._dostore(oid=oid, data='0', already_pickled=True)
+
+ # recover the newly added backend
self._storage._recover_impl('5')
self.assertEquals([], self._storage.storages_degraded)
+ # ensure that we can still write to the RAID
oid2 = self._storage.new_oid()
self._dostore(oid=oid2, data='1', already_pickled=True)
self.assertEquals([], self._storage.storages_degraded)
+ # ensure that all transactions are available from the new backend
self.assertEquals('5', self._storages[-1].name)
s5 = self._storages[-1].open()
self.assertEquals('0', s5.load(oid)[0])
self.assertEquals('1', s5.load(oid2)[0])
+
s5.close()
def test_reload_remove(self):
- # Remove the 4th storage
- storages = [s for c,s in enumerate(self._storages) if c != 3]
- filename = self.saveConfig(storages)
+ self.assertEquals(len(self._storage.storages_degraded), 0)
- # test if the storage was removed (disabled, actually)
- self.assertEquals(len(self._storage.storages_degraded), 0)
- self._storage.raid_reload(filename)
+ del self._storages[3]
+
+ # configure the RAID to no longer use the removed backend
+ self.update_config()
+ self._storage.raid_reload()
self.assertEquals(len(self._storage.storages_degraded), 1)
- # do a simple store to see if anything breaks
+ # ensure that we can still write to the RAID
self._dostore()
More information about the Checkins
mailing list