odoo_utility_scripts/upgrade_custom_addons.py

161 lines
5.3 KiB
Python

import os
import sys
import argparse
import subprocess
import configparser
import psycopg2
def get_custom_addons_modules(addons_path):
"""
Scans the given addons path and returns a list of directory names
that contain a __manifest__.py file.
"""
modules = []
if not os.path.exists(addons_path):
print(f"Error: Addons path '{addons_path}' does not exist.")
return []
for item in os.listdir(addons_path):
item_path = os.path.join(addons_path, item)
if os.path.isdir(item_path):
manifest_path = os.path.join(item_path, '__manifest__.py')
if os.path.exists(manifest_path):
modules.append(item)
return modules
def get_db_params(config_path):
"""
Parses the Odoo config file to extract database connection parameters.
"""
config = configparser.ConfigParser()
try:
config.read(config_path)
except Exception as e:
print(f"Error reading config file: {e}")
return {}
db_params = {}
if 'options' in config:
params = config['options']
db_params['host'] = params.get('db_host', 'localhost')
db_params['port'] = params.get('db_port', '5432')
db_params['user'] = params.get('db_user', 'odoo')
db_params['password'] = params.get('db_password', '')
return db_params
def get_installed_modules(modules_list, db_name, db_params):
"""
Connects to the database and filters the given list of modules specifically
for those that are installed (state='installed').
"""
installed_modules = []
conn_params = {
'dbname': db_name,
'user': db_params.get('user', 'odoo'),
'password': db_params.get('password', ''),
'host': db_params.get('host', 'localhost'),
'port': db_params.get('port', '5432')
}
# Filter out empty or None values to use defaults or avoid errors
conn_params = {k: v for k, v in conn_params.items() if v}
try:
conn = psycopg2.connect(**conn_params)
cur = conn.cursor()
# Check if modules are installed
if not modules_list:
return []
query = "SELECT name FROM ir_module_module WHERE state = 'installed' AND name IN %s"
cur.execute(query, (tuple(modules_list),))
rows = cur.fetchall()
installed_modules = [row[0] for row in rows]
cur.close()
conn.close()
except psycopg2.Error as e:
print(f"Database error: {e}")
print("Ensure psycopg2 matches the server configuration.")
return []
except Exception as e:
print(f"Error checking installed modules: {e}")
return []
return installed_modules
def main():
parser = argparse.ArgumentParser(description="Upgrade installed modules in customaddons for a specific database.")
parser.add_argument('-d', '--database', required=True, help="Database name to upgrade modules on.")
parser.add_argument('-c', '--config', required=True, help="Path to Odoo configuration file.")
parser.add_argument('--odoo-bin', default='./odoo/odoo-bin', help="Path to odoo-bin executable (default: ./odoo/odoo-bin)")
args = parser.parse_args()
# Determine customaddons path relative to this script
script_dir = os.path.dirname(os.path.abspath(__file__))
custom_addons_path = os.path.join(script_dir, 'customaddons')
print(f"Scanning for modules in {custom_addons_path}...")
modules = get_custom_addons_modules(custom_addons_path)
if not modules:
print("No modules found in customaddons.")
sys.exit(0)
print(f"Found {len(modules)} local modules.")
# Get DB params from config
db_params = get_db_params(args.config)
print(f"Checking installed status in database '{args.database}'...")
installed_modules = get_installed_modules(modules, args.database, db_params)
if not installed_modules:
print("None of the local modules are installed in the specified database.")
sys.exit(0)
print(f"Found {len(installed_modules)} installed modules to upgrade.")
# Construct the Odoo command
modules_str = ','.join(installed_modules)
# Check if odoo-bin exists
if not os.path.exists(args.odoo_bin) and not os.path.exists(os.path.abspath(args.odoo_bin)):
print(f"Error: odoo-bin not found at {args.odoo_bin}")
sys.exit(1)
cmd = [
sys.executable,
args.odoo_bin,
'-c', args.config,
'-d', args.database,
'-u', modules_str,
'--stop-after-init'
]
print("--------------------------------------------------")
print(f"Starting upgrade for database '{args.database}'...")
print(f"Modules to upgrade: {modules_str}")
print(f"Command: {' '.join(cmd)}")
print("--------------------------------------------------")
try:
subprocess.run(cmd, check=True)
print("--------------------------------------------------")
print("Upgrade completed successfully.")
except subprocess.CalledProcessError as e:
print("--------------------------------------------------")
print(f"Error: Upgrade failed with exit code {e.returncode}")
sys.exit(e.returncode)
except Exception as e:
print(f"An unexpected error occurred: {e}")
sys.exit(1)
if __name__ == "__main__":
main()