Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions addons/bus/models/bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ def sendmany(self, notifications):
# transaction is not commited yet, there will be nothing to fetch,
# and the longpolling will return no notification.
def notify():
wf = odoo.tools.config.get('webfaction', default=False)
if wf:
db_base = odoo.tools.config["webfaction_db_base"]
with odoo.sql_db.db_connect(db_base).cursor() as cr2:
cr2.execute("notify imbus, %s", (json_dump(list(channels)),))
return

with odoo.sql_db.db_connect('postgres').cursor() as cr:
cr.execute("notify imbus, %s", (json_dump(list(channels)),))
self._cr.after('commit', notify)
Expand Down Expand Up @@ -155,6 +162,29 @@ def poll(self, dbname, channels, last, options=None, timeout=TIMEOUT):
def loop(self):
""" Dispatch postgres notifications to the relevant polling threads/greenlets """
_logger.info("Bus.loop listen imbus on db postgres")
wf = odoo.tools.config.get('webfaction', default=False)
if wf:
db_base = odoo.tools.config["webfaction_db_base"]
with odoo.sql_db.db_connect(db_base).cursor() as cr:
conn = cr._cnx
cr.execute("listen imbus")
cr.commit();
while True:
if select.select([conn], [], [], TIMEOUT) == ([], [], []):
pass
else:
conn.poll()
channels = []
while conn.notifies:
channels.extend(json.loads(conn.notifies.pop().payload))
# dispatch to local threads/greenlets
events = set()
for channel in channels:
events.update(self.channels.pop(hashable(channel), []))
for event in events:
event.set()
return

with odoo.sql_db.db_connect('postgres').cursor() as cr:
conn = cr._cnx
cr.execute("listen imbus")
Expand Down
91 changes: 91 additions & 0 deletions odoo/service/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,29 @@ def _initialize_db(id, db_name, demo, lang, user_password, login='admin', countr
_logger.exception('CREATE DATABASE failed:')

def _create_empty_database(name):
wf = odoo.tools.config.get('webfaction', default=False)
if wf:
_logger.info("WebFaction: Creating database '%s'...", name)
db_base = odoo.tools.config["webfaction_db_base"]
db_user = odoo.tools.config["db_user"]
res = exec_webfaction_sql(db_base, db_user, "SELECT datname FROM pg_database WHERE datname = %s", (name,))
if res!=[]:
raise DatabaseExists("database %r already exists!" % (name,))

db_password = odoo.tools.config["db_password"]

import xmlrpclib
server = xmlrpclib.ServerProxy(odoo.tools.config['webfaction_url'])
session_id, _ = server.login(odoo.tools.config['webfaction_user'], odoo.tools.config['webfaction_password'])
dbus = [ y['username'] for y in filter(lambda x: x['db_type']=='postgresql', server.list_db_users(session_id))]

server.create_db(session_id, name, 'postgresql', db_password)
server.make_user_owner_of_db(session_id, db_user, name, 'postgresql')
if name not in dbus:
server.delete_db_user(session_id, name, 'postgresql')
_logger.info("WebFaction: Database '%s' created.", name)
return

db = odoo.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
chosen_template = odoo.tools.config['db_template']
Expand Down Expand Up @@ -118,6 +141,10 @@ def exp_create_database(db_name, demo, lang, user_password='admin', login='admin

@check_db_management_enabled
def exp_duplicate_database(db_original_name, db_name):
wf = odoo.tools.config.get('webfaction', default=False)
if wf:
raise Exception("A WebFaction database duplication is not yet implemented")

_logger.info('Duplicate database `%s` to `%s`.', db_original_name, db_name)
odoo.sql_db.close_db(db_original_name)
db = odoo.sql_db.db_connect('postgres')
Expand Down Expand Up @@ -161,6 +188,16 @@ def exp_drop(db_name):
odoo.modules.registry.Registry.delete(db_name)
odoo.sql_db.close_db(db_name)

wf = odoo.tools.config.get('webfaction', default=False)
if wf:
_logger.info("WebFaction: Dropping database '%s'...", db_name)
import xmlrpclib
server = xmlrpclib.ServerProxy(odoo.tools.config['webfaction_url'])
session_id, _ = server.login(odoo.tools.config['webfaction_user'], odoo.tools.config['webfaction_password'])
server.delete_db(session_id, db_name, 'postgresql')
_logger.info("WebFaction: Database '%s' dropped.", db_name)
return True

db = odoo.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
cr.autocommit(True) # avoid transaction block
Expand Down Expand Up @@ -310,6 +347,10 @@ def restore_db(db, dump_file, copy=False):

@check_db_management_enabled
def exp_rename(old_name, new_name):
wf = odoo.tools.config.get('webfaction', default=False)
if wf:
raise Exception("A WebFaction database cannot be renamed. Not supported by Webfaction API")

odoo.modules.registry.Registry.delete(old_name)
odoo.sql_db.close_db(old_name)

Expand Down Expand Up @@ -371,6 +412,19 @@ def list_dbs(force=False):

chosen_template = odoo.tools.config['db_template']
templates_list = tuple(set(['postgres', chosen_template]))

wf = odoo.tools.config.get('webfaction', default=False)
if wf:
_logger.info("WebFaction: Listing databases (force=%s)..." % force)
db_base = odoo.tools.config["webfaction_db_base"]
templates_list = tuple(list(templates_list) + [db_base])
db_user = odoo.tools.config["db_user"]
res = exec_webfaction_sql(db_base, db_user, "select datname from pg_database where datdba=(select usesysid from pg_user where usename=%s) and datname not in %s order by datname", (db_user, templates_list))
res = [odoo.tools.ustr(name) for (name,) in res]
_logger.info("WebFaction: Database listing done. %s" % res)
res.sort()
return res

db = odoo.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
try:
Expand Down Expand Up @@ -448,3 +502,40 @@ def dispatch(method, params):
return g[exp_method_name](*params)
else:
raise KeyError("Method not found: %s" % method)

def exec_webfaction_sql(db_base, db_user, sql, params=()):
db = odoo.sql_db.db_connect(db_base)
ok = False
while not ok:
try:
with closing(db.cursor()) as cr:
cr.execute(sql, params)
res = cr.fetchall()
ok = True
except psycopg2.OperationalError as e:
# The next use of regular expressions is just a temporary solution. It's dirty, unelegant, unstable but fast to implement, really fast.
# Of course, it needs to be corrected ASAP and implement an elegant solution.
import re
m1 = re.search('^FATAL: no pg_hba.conf entry for host "[0-9.]+", user "%(db_user)s", database "%(db_base)s", SSL on\nFATAL: no pg_hba.conf entry for host "[0-9.]+", user "%(db_user)s", database "%(db_base)s", SSL off\n$' % dict(db_user=db_user, db_base=db_base), unicode(e))
m2 = re.search('^FATAL: no pg_hba.conf entry for host "\[local\]", user "%(db_user)s", database "%(db_base)s", SSL off\n$' % dict(db_user=db_user, db_base=db_base), unicode(e))
if m1 is None and m2 is None:
m = re.search('^FATAL: permission denied for database "%s"\nDETAIL: User does not have CONNECT privilege.$' % db_base, unicode(e))
if m is not None:
_logger.info('WebFaction: Base database "%s" already created but user "%s" has no permissions -> Granting full access...' % (db_base, db_user))
import xmlrpclib
server = xmlrpclib.ServerProxy(odoo.tools.config['webfaction_url'])
session_id, _ = server.login(odoo.tools.config['webfaction_user'], odoo.tools.config['webfaction_password'])
server.grant_db_permissions(session_id, db_user, db_base, 'postgresql')
_logger.info('WebFaction: User "%s" permissions to base database "%s" granted successfully.' % (db_user, db_base))
else:
raise Exception("Unexpected error message string '%s'" % unicode(e))
else:
_logger.info('WebFaction: Base database "%s" does not exist -> Creating...' % db_base)
import xmlrpclib
server = xmlrpclib.ServerProxy(odoo.tools.config['webfaction_url'])
session_id, _ = server.login(odoo.tools.config['webfaction_user'], odoo.tools.config['webfaction_password'])
server.create_db(session_id, db_base, 'postgresql', db_base)
server.make_user_owner_of_db(session_id, db_user, db_base, 'postgresql')
server.delete_db_user(session_id, db_base, 'postgresql')
_logger.info('WebFaction: Base database "%s" created successfully.' % db_base)
return res