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")
def test_minor_upgrade(self): """ Simulate the tag version was bumped from x.x.1.x to x.x.2.x """ self.registerTestInstance('test-7000') # instance is stopped, this should start it montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) old_tag = montysolrupdate.get_release_tag("test-7000/RELEASE") new_tag = copy.copy(old_tag) new_tag.minor = new_tag.minor + 1 self.assertTrue(os.path.exists("test-7000_%s" % str(old_tag)), "booork") self.assertTrue(os.path.exists("test-7000_%s_data" % str(old_tag)), "booork") self.assertTrue(not os.path.exists("test-7000_%s" % str(new_tag)), "booork") self.assertTrue(not os.path.exists("test-7000_%s_data" % str(new_tag)), "booork") self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % old_tag)) self.isRunning(7000) open("test-7000_data/foo", 'w').write('index') self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'cp -r montysolr/build/contrib/examples/adsabs test-7000_*', 'ln -s test-7000_* test-7000', 'mkdir test-7000_*_data', 'ln -s */perpetuum/test-7000_*_data */perpetuum/test-7000/solr/data', 'ln -s test-7000_*_data test-7000_data', 'cp solr/collection1/conf/solrconfig.xml solr/collection1/conf/solrconfig.xml.orig', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) # now simulate update def tag_up(tag): tag.minor = tag.minor + 1 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 minor', lambda x,y,z: True) self.cmd_collector = [] montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.isRunning(7000) self.isNotRunning(7010) self.assertTrue(os.path.exists("test-7000_%s" % str(old_tag)), "booork") self.assertTrue(os.path.exists("test-7000_%s_data" % str(old_tag)), "booork") self.assertTrue(os.path.exists("test-7000_%s" % str(new_tag)), "missing test-7000_%s" % str(new_tag)) self.assertTrue(os.path.exists("test-7000_%s_data" % str(new_tag)), "test-7000_%s_data" % str(new_tag)) self.assertTrue(os.path.exists("test-7000_data/foo"), "Something was improperly copied during upgrade") self.assertTrue(os.path.exists("test-7000_%s_data/foo" % str(old_tag)), "Something was improperly copied during upgrade") self.assertTrue(os.path.exists("test-7000_%s_data/foo" % str(new_tag)), "Something was improperly copied during upgrade") open("test-7000_data/bar", 'w').write('index') self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % new_tag)) self.assertTrue(os.path.exists("test-7000_%s_data/bar" % new_tag)) self.assertTrue(not os.path.exists("test-7000_%s_data/bar" % old_tag)) self.assertTrue(os.path.exists("test-7000_data/foo"), "Something was improperly copied during upgrade") self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'chmod u+x build-montysolr.sh', 'git checkout -f -b refs/tags/*', './build-montysolr.sh minor', # <- recompilation 'chmod u+x ./build-example.sh', './build-example.sh *', # <- assemble example 'cp -r montysolr/build/contrib/examples/adsabs test-7000_*', 'rm -fr test-7000_%s/solr/data' % str(new_tag), 'mkdir test-7000_%s_data' % str(new_tag), 'cp -fR test-7000_data/* test-7000_%s_data' % str(new_tag), 'kill *', 'rm test-7000', 'rm test-7000_data', 'ln -s test-7000_%s test-7000' % str(new_tag), 'ln -s test-7000_%s_data test-7000_data' % str(new_tag), 'ln -s */perpetuum/test-7000_data test-7000_%s/solr/data' % str(new_tag), 'cp solr/collection1/conf/solrconfig.xml solr/collection1/conf/solrconfig.xml.orig', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) self.isRunning(7000)
def test_patch_upgrade(self): """ Simulate the tag version was bumped from x.x.x.1 to x.x.x.2 """ self.registerTestInstance('test-7000') self.assertTrue(not os.path.exists("test-7000"), "booork") self.assertTrue(not os.path.exists("test-7000_data"), "booork") # instance is stopped, this should start it montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) old_tag = montysolrupdate.get_release_tag("test-7000/RELEASE") new_tag = copy.copy(old_tag) new_tag.patch = new_tag.patch + 1 self.assertTrue(os.path.exists("test-7000_%s" % str(old_tag)), "booork") self.assertTrue(os.path.exists("test-7000_%s_data" % str(old_tag)), "booork") self.assertTrue(not os.path.exists("test-7000_%s" % str(new_tag)), "booork") self.assertTrue(not os.path.exists("test-7000_%s_data" % str(new_tag)), "booork") self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % old_tag)) self.isRunning(7000) open("test-7000_data/foo", 'w').write('index') self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'cp -r montysolr/build/contrib/examples/adsabs test-7000_*', 'ln -s test-7000_* test-7000', 'mkdir test-7000_*_data', 'ln -s */perpetuum/test-7000_*_data */perpetuum/test-7000/solr/data', 'ln -s test-7000_*_data test-7000_data', 'cp solr/collection1/conf/solrconfig.xml solr/collection1/conf/solrconfig.xml.orig', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) # now simulate update def tag_up(tag): tag.patch = tag.patch + 1 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.cmd_collector = [] self.isRunning(7000) montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.isRunning(7000) self.isNotRunning(7010) self.assertTrue(os.path.exists("test-7000_%s" % str(old_tag)), "The old instance must exist") self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The new instance data should still point to old instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7000")) == os.path.abspath("test-7000_%s" % str(new_tag)), "The new instance should point to new instance folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data/solr/data")) == os.path.abspath("test-7000_%s_data/solr/data" % str(old_tag)), "The new instance solr/data should point to old instance data folder") self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'chmod u+x build-montysolr.sh', 'git checkout -f -b refs/tags/*', './build-montysolr.sh patch', # <- recompilation 'chmod u+x ./build-example.sh', './build-example.sh *', # <- assemble example 'kill *', 'cp -r montysolr/build/contrib/examples/adsabs test-7000_%s' % str(new_tag), 'rm -fr test-7000_%s/solr/data' % str(new_tag), 'ln -s */perpetuum/test-7000_data test-7000_%s/solr/data' % str(new_tag), 'rm test-7000', 'ln -s test-7000_%s test-7000' % str(new_tag), 'cp solr/collection1/conf/solrconfig.xml solr/collection1/conf/solrconfig.xml.orig', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) # run it again previous_tag = str(new_tag) new_tag.patch = new_tag.patch + 1 self.cmd_collector = [] self.isRunning(7000) montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.isRunning(7000) self.isNotRunning(7010) self.assertTrue(os.path.exists("test-7000_%s" % str(previous_tag)), "The old instance must exist") self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data")) == os.path.abspath("test-7000_%s_data" % str(old_tag)), "The new instance data should still point to old instance data folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7000")) == os.path.abspath("test-7000_%s" % str(new_tag)), "The new instance should point to new instance folder") self.assertTrue(os.path.abspath(os.path.realpath("test-7000_data/solr/data")) == os.path.abspath("test-7000_%s_data/solr/data" % str(old_tag)), "The new instance solr/data should point to old instance data folder") self.cmd_collector = [] self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'chmod u+x build-montysolr.sh', 'git checkout -f -b refs/tags/*', './build-montysolr.sh patch', # <- recompilation 'chmod u+x ./build-example.sh', './build-example.sh *', # <- assemble example 'kill *', 'cp -r montysolr/build/contrib/examples/adsabs test-7000_%s' % str(new_tag), 'rm -fr test-7000_%s/solr/data' % str(new_tag), 'ln -s */perpetuum/test-7000_data test-7000_%s/solr/data' % str(new_tag), 'rm test-7000', 'ln -s test-7000_%s test-7000' % str(new_tag), 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) # and now check that no-change does not trigger recompilation self.cmd_collector = [] self.interceptTag('perpetuum/montysolr', lambda t: t) self.intercept('./build-example.sh .*', lambda x,y,z: 1/0) self.intercept('./build-montysolr.sh patch', lambda x,y,z: 1/0) montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', )
def test_major_upgrade(self): """ Simulate the tag version was bumped from 40.x.x.x to 41.x.x.x or x.1.x.x to x.2.x.x """ self.registerTestInstance('test-7000') self.registerTestInstance('next-release_test-7010') # instance is stopped, this should start it montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.isRunning(7000) old_tag = montysolrupdate.get_release_tag("test-7000/RELEASE") new_tag = copy.copy(old_tag) self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'cp -r montysolr/build/contrib/examples/adsabs test-7000_*', 'ln -s test-7000_* test-7000', 'mkdir test-7000_*_data', 'ln -s */perpetuum/test-7000_*_data */perpetuum/test-7000/solr/data', 'ln -s test-7000_*_data test-7000_data', 'cp solr/collection1/conf/solrconfig.xml solr/collection1/conf/solrconfig.xml.orig', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) # 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) if random.choice([0,1]) == 1: new_tag.major = new_tag.major + 1 else: new_tag.solr_ver = new_tag.solr_ver + 1 # but do not bother to re-compile self.intercept('./build-example.sh .*', lambda x,y,z: True) self.intercept('./build-montysolr.sh nuke', lambda x,y,z: True) self.cmd_collector = [] montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.isRunning(7000) self.isRunning(7010) self.assertTrue(os.path.exists("next-release_test-7000"), "New major upgrade did not create next-release") open("next-release_test-7000/foo", 'w').write('foo') self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'chmod u+x build-montysolr.sh', 'git checkout -f -b refs/tags/*', './build-montysolr.sh nuke', # <-- build everything from scratch 'chmod u+x ./build-example.sh', './build-example.sh *', 'cp -r montysolr/build/contrib/examples/adsabs test-7000_*', 'mkdir test-7000_*_data', 'ln -s test-7000_* next-release_test-7000', 'ln -s test-7000_*_data next-release_test-7000_data', 'rm -fr test-7000_*/solr/data', 'ln -s */perpetuum/test-7000_*_data */perpetuum/next-release_test-7000/solr/data', 'cp solr/collection1/conf/solrconfig.xml solr/collection1/conf/solrconfig.xml.orig', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' ) # the next invocation of the same command should replace the existing instance # with the next-release, TODO: check index is rebuilt self.cmd_collector = [] montysolrupdate.main(['foo', '-c', '-u', '-t', '10', 'test-7000']) self.assertTrue(not os.path.exists("next-release_test-7000"), "this invocation should have replace existing with the next-release") self.checkCommandSequence( 'git fetch', 'git reset --hard origin/master', 'git checkout master', 'kill *', # it stops next-release 'kill *', # stops test-7000 'rm test-7000', # removes symlinks 'rm test-7000_data', 'ln -s /tmp/montysolrupdate-test/perpetuum/test-7000_* test-7000', 'ln -s /tmp/montysolrupdate-test/perpetuum/test-7000_*_data test-7000_data', 'rm next-release_test-7000', # removes next-release 'rm next-release_test-7000_data', 'chmod u+x automatic-run.sh', 'bash -e ./automatic-run.sh &' # starts the service again ) self.isRunning(7000) self.isNotRunning(7010) self.assertTrue(os.path.exists("test-7000/foo"), "Something was improperly copied during upgrade")