def setUp(self): TestCase.setUp(self) if os.path.exists('update.pid'): montysolrupdate.remove_lock('update.pid') time.sleep(0.2) self.to_kill = [] self.old_get = montysolrupdate.get_latest_git_release_tag self.tagInterceptors = {} self.tagRestorers = {} def mocker(path): tag = self.old_get(path) p = os.path.abspath(path) for k,v in self.tagInterceptors.items(): if k in p: if p in self.tagRestorers: v(self.tagRestorers[p][1]) return self.tagRestorers[p][1] else: new_tag = copy.copy(tag) v(new_tag) self.tagRestorers[p] = (tag, new_tag) return new_tag return tag montysolrupdate.get_latest_git_release_tag = mocker self.old_run_cmd = montysolrupdate.run_cmd self.interceptor = {} self.cmd_collector = [] def run_cmd(args, silent=False, strict=True): cmd = ' '.join(map(str, args)) self.cmd_collector.append(cmd) for pattern in self.interceptor: if pattern.match(cmd): return self.interceptor[pattern](args, silent, strict) else: return self.old_run_cmd(args, silent, strict) montysolrupdate.run_cmd = run_cmd
def test_reader_writer_upgrade(self): """ Simulate having one read-write masters and two read-only (searchers) """ self.registerTestInstance('test-7000') self.registerTestInstance('test-7001') self.registerTestInstance('test-7002') self.registerTestInstance('next-release_test-7000') self.registerTestInstance('next-release_test-7001') self.registerTestInstance('next-release_test-7002') self.assertTrue(not os.path.exists("test-7000"), "booork") self.assertTrue(not os.path.exists("test-7000_data"), "booork") self.assertTrue(not os.path.exists("test-7001"), "booork") self.assertTrue(not os.path.exists("test-7001_data"), "booork") self.assertTrue(not os.path.exists("test-7002"), "booork") self.assertTrue(not os.path.exists("test-7002_data"), "booork") # instance is stopped, this should start it montysolrupdate.main(['foo', '-c', '-a', '-u', '-t', '10', 'test-7000#w', 'test-7001#r', 'test-7002#r']) old_tag = montysolrupdate.get_release_tag("test-7000/RELEASE") new_tag = copy.copy(old_tag) self.assertTrue(os.path.exists("test-7000_%s" % str(old_tag)), "The writer instance must exist") self.assertTrue(os.path.exists("test-7001_%s" % str(old_tag)), "The reader#1 instance must exist") self.assertTrue(os.path.exists("test-7002_%s" % str(old_tag)), "The reader#2 instance must exist") self.assertTrue(os.path.exists("test-7000_%s_data" % str(old_tag)), "The writer instance data must exist") self.assertTrue(os.path.abspath(os.path.realpath("test-7001_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The reader#1 instance data should point to writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7002_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The reader#2 instance data should point to writer instance data folder") self.isRunning(7000) self.isRunning(7001) self.isRunning(7002) open("test-7000_data/foo", 'w').write('index') # now simulate update def tag_up(tag): tag.solr_ver = new_tag.solr_ver tag.major = new_tag.major tag.minor = new_tag.minor tag.patch = new_tag.patch self.interceptTag('perpetuum/montysolr', tag_up) # but do not bother to re-compile self.intercept('./build-example.sh', lambda x,y,z: True) self.intercept('./build-montysolr.sh patch', lambda x,y,z: True) self.intercept('./build-montysolr.sh minor', lambda x,y,z: True) self.intercept('./build-montysolr.sh nuke', lambda x,y,z: True) # OK, let's go! new_tag.patch = new_tag.patch + 1 montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000#w', 'test-7001#r', 'test-7002#r']) self.isRunning(7000) self.isRunning(7001) self.isRunning(7002) self.assertTrue(os.path.exists("test-7000_%s" % str(new_tag)), "The writer instance must exist") self.assertTrue(os.path.exists("test-7001_%s" % str(new_tag)), "The reader#1 instance must exist") self.assertTrue(os.path.exists("test-7002_%s" % str(new_tag)), "The reader#2 instance must exist") self.assertTrue(os.path.exists("test-7000_%s_data" % str(old_tag)), "The writer instance data must exist") # and still point to the same folder self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The writer instance data should point to the old writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7001_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The reader#1 instance data should point to writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7002_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The reader#2 instance data should point to writer instance data folder") # major upgrade new_tag.major = new_tag.major + 1 # this will create a next-release instances that run alongside the old montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000#w', 'test-7001#r', 'test-7002#r']) self.isRunning(7000) self.isRunning(7001) self.isRunning(7002) self.isRunning(7010) self.isRunning(7011) self.isRunning(7012) self.assertTrue(os.path.abspath(os.path.realpath("next-release_test-7000")) == os.path.abspath("test-7000_%s" % str(new_tag)), "The writer instance should point to the old writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("next-release_test-7001")) == os.path.abspath("test-7001_%s" % str(new_tag)), "The reader#1 instance should point to writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("next-release_test-7002")) == os.path.abspath("test-7002_%s" % str(new_tag)), "The reader#2 instance should point to writer instance data folder") # data and still point to the same folder self.assertTrue(os.path.abspath(os.path.realpath("next-release_test-7000_data")) == os.path.abspath("test-7000_%s_data" % str(new_tag)), "The writer instance data should point to the old writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("next-release_test-7001_data")) == os.path.abspath("test-7000_%s_data" % str(new_tag)), "The reader#1 instance data should point to writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("next-release_test-7002_data")) == os.path.abspath("test-7000_%s_data" % str(new_tag)), "The reader#2 instance data should point to writer instance data folder") # let's confuse it and upgrade while the next branch is still building # it should refuse to prepare a new instance with the latest patch alongside the next- new_tag.major = new_tag.major - 1 new_tag.patch = new_tag.patch + 1 old_idle = montysolrupdate.is_invenio_doctor_idle try: montysolrupdate.is_invenio_doctor_idle = lambda x: False montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000#w', 'test-7001#r', 'test-7002#r']) except: montysolrupdate.remove_lock('update.pid') time.sleep(0.2) finally: montysolrupdate.is_invenio_doctor_idle = old_idle self.isRunning(7000) self.isRunning(7001) self.isRunning(7002) self.isRunning(7010) self.isRunning(7011) self.isRunning(7012) # and the next invocation should replace the old release with the next-release new_tag.major = new_tag.major + 1 new_tag.patch = new_tag.patch - 1 montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000#w', 'test-7001#r', 'test-7002#r']) self.isRunning(7000) self.isRunning(7001) self.isRunning(7002) self.isNotRunning(7010) self.isNotRunning(7011) self.isNotRunning(7012) self.assertFalse(os.path.exists("next-release_test-7000"), "It must be removed") self.assertFalse(os.path.exists("next-release_test-7000_data"), "It must be removed") self.assertFalse(os.path.exists("next-release_test-7001"), "It must be removed") self.assertFalse(os.path.exists("next-release_test-7001_data"), "It must be removed") self.assertFalse(os.path.exists("next-release_test-7002"), "It must be removed") self.assertFalse(os.path.exists("next-release_test-7002_data"), "It must be removed") self.assertTrue(os.path.abspath(os.path.realpath("test-7000")) == os.path.abspath("test-7000_%s" % str(new_tag)), "The writer instance should point to the old writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7001")) == os.path.abspath("test-7001_%s" % str(new_tag)), "The reader#1 instance should point to writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7002")) == os.path.abspath("test-7002_%s" % str(new_tag)), "The reader#2 instance should point to writer instance data folder") # data and still point to the same folder self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % str(new_tag)), "The writer instance data should point to the old writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7001_data")) == os.path.abspath(os.path.realpath("test-7000_data")), "The reader#1 instance data should point to writer instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7002_data")) == os.path.abspath(os.path.realpath("test-7000_data")), "The reader#2 instance data should point to writer instance data folder")