[IMP] core: new neutralize flag on database restore and database duplicate dialog

Before this PR:
The only way to neutralize the database is running cli command neutralize

After this PR:
There is a new checkbox "neutralize database" in Duplicate database and Restore database dialog that neutralize the database after duplication/restore.
I also moved the neutralization code to the external module so it can be called also outside the cli .

closes odoo/odoo#122185

X-original-commit: 616740e9d09b3d0376be43ed1489e390f6f5823e
Signed-off-by: Julien Castiaux (juc) <juc@odoo.com>
This commit is contained in:
Michele
2023-05-24 11:53:38 +02:00
parent d95ef62181
commit 724df8a570
6 changed files with 46 additions and 13 deletions
+4 -4
View File
@@ -88,14 +88,14 @@ class Database(http.Controller):
return self._render_template(error=error)
@http.route('/web/database/duplicate', type='http', auth="none", methods=['POST'], csrf=False)
def duplicate(self, master_pwd, name, new_name):
def duplicate(self, master_pwd, name, new_name, neutralize_database=False):
insecure = odoo.tools.config.verify_admin_password('admin')
if insecure and master_pwd:
dispatch_rpc('db', 'change_admin_password', ["admin", master_pwd])
try:
if not re.match(DBNAME_PATTERN, new_name):
raise Exception(_('Invalid database name. Only alphanumerical characters, underscore, hyphen and dot are allowed.'))
dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name])
dispatch_rpc('db', 'duplicate_database', [master_pwd, name, new_name, neutralize_database])
if request.db == name:
request.env.cr.close() # duplicating a database leads to an unusable cursor
return request.redirect('/web/database/manager')
@@ -141,7 +141,7 @@ class Database(http.Controller):
return self._render_template(error=error)
@http.route('/web/database/restore', type='http', auth="none", methods=['POST'], csrf=False)
def restore(self, master_pwd, backup_file, name, copy=False):
def restore(self, master_pwd, backup_file, name, copy=False, neutralize_database=False):
insecure = odoo.tools.config.verify_admin_password('admin')
if insecure and master_pwd:
dispatch_rpc('db', 'change_admin_password', ["admin", master_pwd])
@@ -150,7 +150,7 @@ class Database(http.Controller):
db.check_super(master_pwd)
with tempfile.NamedTemporaryFile(delete=False) as data_file:
backup_file.save(data_file)
db.restore_db(name, data_file.name, str2bool(copy))
db.restore_db(name, data_file.name, str2bool(copy), neutralize_database)
return request.redirect('/web/database/manager')
except Exception as e:
error = "Database restore error: %s" % (str(e) or repr(e))
@@ -134,6 +134,12 @@
<input id="dbname_restore" type="text" name="name" class="form-control" required="required" t-att-pattern="pattern" title="Only alphanumerical characters, underscore, hyphen and dot are allowed"/>
</div>
</div>
<div class="row mb-3">
<label for="dbname_duplicate" class="col-md-4 col-form-label" >Neutralize</label>
<div class="col-md-8">
<input id="neutralize_database_restore" type="checkbox" name="neutralize_database" class="form-check-input" />
</div>
</div>
<label for="radio_copy_true">This database might have been moved or copied.</label>
<p class="form-text">
In order to avoid conflicts between databases, Odoo needs to know if this database was moved or copied.<br/>
@@ -211,6 +217,12 @@
<input id="new_name" type="text" name="new_name" class="form-control" required="required" t-att-pattern="pattern" title="Only alphanumerical characters, underscore, hyphen and dot are allowed"/>
</div>
</div>
<div class="row mb-3">
<label for="dbname_duplicate" class="col-md-4 col-form-label" >Neutralize</label>
<div class="col-md-8">
<input id="neutralize_database" type="checkbox" name="neutralize_database" class="form-check-input" />
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" value="Continue" class="btn btn-primary float-end"/>
+10 -2
View File
@@ -50,6 +50,10 @@ class Db(Command):
'-f', '--force', action='store_const', default=False, const=True,
help="delete `database` database before loading if it exists"
)
load.add_argument(
'-n', '--neutralize', action='store_const', default=False, const=True,
help="neutralize the database after restore"
)
load.add_argument(
'database', nargs='?',
help="database to create, defaults to dump file's name "
@@ -76,6 +80,10 @@ class Db(Command):
'-f', '--force', action='store_const', default=False, const=True,
help="delete `target` database before copying if it exists"
)
duplicate.add_argument(
'-n', '--neutralize', action='store_const', default=False, const=True,
help="neutralize the target database after duplicate"
)
duplicate.add_argument("source")
duplicate.add_argument("target", help="database to copy `source` to, must not exist unless `-f` is specified in which case it will be dropped first")
@@ -134,7 +142,7 @@ class Db(Command):
exit("Not a zipped dump file, use `pg_restore` to restore raw dumps,"
" and `psql` to execute sql dumps or scripts.")
restore_db(db=db_name, dump_file=dump_file, copy=True)
restore_db(db=db_name, dump_file=dump_file, copy=True, neutralize_database=args.neutralize)
def dump(self, args):
if args.dump_path == '-':
@@ -145,7 +153,7 @@ class Db(Command):
def duplicate(self, args):
self._check_target(args.target, delete_if_exists=args.force)
exp_duplicate_database(args.source, args.target)
exp_duplicate_database(args.source, args.target, neutralize_database=args.neutralize)
def rename(self, args):
self._check_target(args.target, delete_if_exists=args.force)
+4 -5
View File
@@ -33,9 +33,9 @@ class Neutralize(Command):
try:
with odoo.sql_db.db_connect(dbname).cursor() as cursor:
installed_modules = odoo.modules.neutralize.get_installed_modules(cursor)
queries = odoo.modules.neutralize.get_neutralization_queries(installed_modules)
if opt.to_stdout:
installed_modules = odoo.modules.neutralize.get_installed_modules(cursor)
queries = odoo.modules.neutralize.get_neutralization_queries(installed_modules)
# pylint: disable=bad-builtin
print('BEGIN;')
for query in queries:
@@ -44,9 +44,8 @@ class Neutralize(Command):
# pylint: disable=bad-builtin
print("COMMIT;")
else:
for query in queries:
cursor.execute(query)
_logger.info("Neutralization finished")
odoo.modules.neutralize.neutralize_database(cursor)
except Exception:
_logger.critical("An error occurred during the neutralization. THE DATABASE IS NOT NEUTRALIZED!")
sys.exit(1)
+9
View File
@@ -2,7 +2,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo
import logging
_logger = logging.getLogger(__name__)
def get_installed_modules(cursor):
cursor.execute('''
@@ -19,3 +21,10 @@ def get_neutralization_queries(modules):
if filename:
with odoo.tools.misc.file_open(filename) as file:
yield file.read().strip()
def neutralize_database(cursor):
installed_modules = get_installed_modules(cursor)
queries = get_neutralization_queries(installed_modules)
for query in queries:
cursor.execute(query)
_logger.info("Neutralization finished")
+7 -2
View File
@@ -142,7 +142,7 @@ def exp_create_database(db_name, demo, lang, user_password='admin', login='admin
return True
@check_db_management_enabled
def exp_duplicate_database(db_original_name, db_name):
def exp_duplicate_database(db_original_name, db_name, neutralize_database=False):
_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')
@@ -160,6 +160,8 @@ def exp_duplicate_database(db_original_name, db_name):
# if it's a copy of a database, force generation of a new dbuuid
env = odoo.api.Environment(cr, SUPERUSER_ID, {})
env['ir.config_parameter'].init(force=True)
if neutralize_database:
odoo.modules.neutralize.neutralize_database(cr)
from_fs = odoo.tools.config.filestore(db_original_name)
to_fs = odoo.tools.config.filestore(db_name)
@@ -284,7 +286,7 @@ def exp_restore(db_name, data, copy=False):
return True
@check_db_management_enabled
def restore_db(db, dump_file, copy=False):
def restore_db(db, dump_file, copy=False, neutralize_database=False):
assert isinstance(db, str)
if exp_db_exist(db):
_logger.warning('RESTORE DB: %s already exists', db)
@@ -328,6 +330,9 @@ def restore_db(db, dump_file, copy=False):
if copy:
# if it's a copy of a database, force generation of a new dbuuid
env['ir.config_parameter'].init(force=True)
if neutralize_database:
odoo.modules.neutralize.neutralize_database(cr)
if filestore_path:
filestore_dest = env['ir.attachment']._filestore()
shutil.move(filestore_path, filestore_dest)