Skip to content

Commit

Permalink
[FIX] runbot: do not use remote cursor for dropping local dbs
Browse files Browse the repository at this point in the history
To find out the list of manually created dbs,
rev. 4d94f45 used the cursor that is connected to the
master `runbot` database, which may reside on a different
cluster/host.

- Add a helper to run commands on the local PG cluster
instead ("postgres" database).
- Modify other commands for local cluster (create/drop db)
to use the same cursor. Rename those methods to _local_*
to better indicate their local effect.
  • Loading branch information
odony committed Jan 18, 2016
1 parent 8067425 commit 9bd4838
Showing 1 changed file with 35 additions and 18 deletions.
53 changes: 35 additions & 18 deletions runbot/runbot.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- encoding: utf-8 -*-

import contextlib
import datetime
import fcntl
import glob
Expand All @@ -8,6 +9,7 @@
import logging
import operator
import os
import psycopg2
import re
import resource
import shutil
Expand Down Expand Up @@ -152,6 +154,16 @@ def uniq_list(l):
def fqdn():
return socket.getfqdn()

@contextlib.contextmanager
def local_pgadmin_cursor():
cnx = None
try:
cnx = psycopg2.connect("dbname=postgres")
cnx.autocommit = True # required for admin commands
yield cnx.cursor()
finally:
if cnx: cnx.close()

#----------------------------------------------------------
# RunBot Models
#----------------------------------------------------------
Expand Down Expand Up @@ -797,17 +809,19 @@ def checkout(self, cr, uid, ids, context=None):
build.write({'server_match': server_match,
'modules': ','.join(modules_to_test)})

def pg_dropdb(self, cr, uid, dbname):
run(['dropdb', dbname])
def _local_pg_dropdb(self, cr, uid, dbname):
with local_pgadmin_cursor() as local_cr:
local_cr.execute('DROP DATABASE IF EXISTS "%s"' % dbname)
# cleanup filestore
datadir = appdirs.user_data_dir()
paths = [os.path.join(datadir, pn, 'filestore', dbname) for pn in 'OpenERP Odoo'.split()]
run(['rm', '-rf'] + paths)

def pg_createdb(self, cr, uid, dbname):
self.pg_dropdb(cr, uid, dbname)
def _local_pg_createdb(self, cr, uid, dbname):
self._local_pg_dropdb(cr, uid, dbname)
_logger.debug("createdb %s", dbname)
run(['createdb', '--encoding=unicode', '--lc-collate=C', '--template=template0', dbname])
with local_pgadmin_cursor() as local_cr:
local_cr.execute("""CREATE DATABASE "%s" TEMPLATE template0 LC_COLLATE 'C' ENCODING 'unicode'""" % dbname)

def cmd(self, cr, uid, ids, context=None):
"""Return a list describing the command to start the build"""
Expand Down Expand Up @@ -906,7 +920,7 @@ def job_00_init(self, cr, uid, build, lock_path, log_path):
def job_10_test_base(self, cr, uid, build, lock_path, log_path):
build._log('test_base', 'Start test base module')
# run base test
self.pg_createdb(cr, uid, "%s-base" % build.dest)
self._local_pg_createdb(cr, uid, "%s-base" % build.dest)
cmd, mods = build.cmd()
if grep(build.server("tools/config.py"), "test-enable"):
cmd.append("--test-enable")
Expand All @@ -915,7 +929,7 @@ def job_10_test_base(self, cr, uid, build, lock_path, log_path):

def job_20_test_all(self, cr, uid, build, lock_path, log_path):
build._log('test_all', 'Start test all modules')
self.pg_createdb(cr, uid, "%s-all" % build.dest)
self._local_pg_createdb(cr, uid, "%s-all" % build.dest)
cmd, mods = build.cmd()
if grep(build.server("tools/config.py"), "test-enable"):
cmd.append("--test-enable")
Expand Down Expand Up @@ -1075,24 +1089,27 @@ def schedule(self, cr, uid, ids, context=None):

# cleanup only needed if it was not killed
if build.state == 'done':
build.cleanup()
build._local_cleanup()

def skip(self, cr, uid, ids, context=None):
self.write(cr, uid, ids, {'state': 'done', 'result': 'skipped'}, context=context)
to_unduplicate = self.search(cr, uid, [('id', 'in', ids), ('duplicate_id', '!=', False)])
if len(to_unduplicate):
self.force(cr, uid, to_unduplicate, context=context)

def cleanup(self, cr, uid, ids, context=None):
def _local_cleanup(self, cr, uid, ids, context=None):
for build in self.browse(cr, uid, ids, context=context):
cr.execute("""
SELECT datname
FROM pg_database
WHERE pg_get_userbyid(datdba) = current_user
AND datname LIKE %s
""", [build.dest + '%'])
for db, in cr.fetchall():
self.pg_dropdb(cr, uid, db)
# Cleanup the *local* cluster
with local_pgadmin_cursor() as local_cr:
local_cr.execute("""
SELECT datname
FROM pg_database
WHERE pg_get_userbyid(datdba) = current_user
AND datname LIKE %s
""", [build.dest + '%'])
to_delete = local_cr.fetchall()
for db, in to_delete:
self._local_pg_dropdb(cr, uid, db)

if os.path.isdir(build.path()) and build.result != 'killed':
shutil.rmtree(build.path())
Expand All @@ -1111,7 +1128,7 @@ def kill(self, cr, uid, ids, result=None, context=None):
build.write(v)
cr.commit()
build.github_status()
build.cleanup()
build._local_cleanup()

def reap(self, cr, uid, ids):
while True:
Expand Down

0 comments on commit 9bd4838

Please sign in to comment.