def cmd_upgrade(upgrader=None): """Command for applying upgrades.""" from flask import current_app from invenio_utils.text import wrap_text_in_a_box, wait_for_user logfilename = os.path.join(current_app.config['CFG_LOGDIR'], 'invenio_upgrader.log') if not upgrader: upgrader = InvenioUpgrader() logger = upgrader.get_logger(logfilename=logfilename) try: upgrades = upgrader.get_upgrades() if not upgrades: logger.info("All upgrades have been applied.") return logger.info("Following upgrade(s) will be applied:") for u in upgrades: title = u['__doc__'] if title: logger.info(" * %s (%s)" % (u['id'], title)) else: logger.info(" * %s" % u['id']) logger.info("Running pre-upgrade checks...") upgrader.pre_upgrade_checks(upgrades) logger.info("Calculating estimated upgrade time...") estimate = upgrader.human_estimate(upgrades) wait_for_user(wrap_text_in_a_box( "WARNING: You are going to upgrade your installation " "(estimated time: %s)!" % estimate)) for u in upgrades: title = u['__doc__'] if title: logger.info("Applying %s (%s)" % (u['id'], title)) else: logger.info("Applying %s" % u['id']) upgrader.apply_upgrade(u) logger.info("Running post-upgrade checks...") upgrader.post_upgrade_checks(upgrades) if upgrader.has_warnings(): logger.warning("Upgrade completed with %s warnings - please check " "log-file for further information:\nless %s" % (upgrader.get_warnings_count(), logfilename)) else: logger.info("Upgrade completed successfully.") except RuntimeError as e: for msg in e.args: logger.error(unicode(msg)) logger.info("Please check log file for further information:\n" "less %s" % logfilename) sys.exit(1)
def drop(yes_i_know=False, quiet=False): """Drop database tables.""" print(">>> Going to drop tables and related data on filesystem ...") from invenio_utils.date import get_time_estimator from invenio_utils.text import wrap_text_in_a_box, wait_for_user from invenio_ext.sqlalchemy.utils import test_sqla_connection, \ test_sqla_utf8_chain from invenio_ext.sqlalchemy import db, models # Step 0: confirm deletion wait_for_user( wrap_text_in_a_box( "WARNING: You are going to destroy your database tables and related " "data on filesystem!")) # Step 1: test database connection test_sqla_connection() test_sqla_utf8_chain() list(models) # Step 2: destroy associated data tables = list(reversed(db.metadata.sorted_tables)) def _dropper(items, prefix, dropper): N = len(items) prefix = prefix.format(N) e = get_time_estimator(N) dropped = 0 if quiet: print(prefix) for i, table in enumerate(items): try: if not quiet: print_progress(1.0 * (i + 1) / N, prefix=prefix, suffix=str( datetime.timedelta(seconds=e()[0]))) dropper(table) dropped += 1 except Exception: print('\r>>> problem with dropping {0}'.format(table)) current_app.logger.exception(table) if dropped == N: print(">>> Everything has been dropped successfully.") else: print("ERROR: not all items were properly dropped.") print(">>> Dropped", dropped, 'out of', N) _dropper(tables, '>>> Dropping {0} tables ...', lambda table: table.drop(bind=db.engine, checkfirst=True))
def test_sqla_connection(): """Test connection with the database.""" print("Test connection... \t", end="") try: from sqlalchemy import inspect from invenio_ext.sqlalchemy import db inspector = inspect(db.engine) inspector.get_table_names() except OperationalError as err: from invenio_utils.text import wrap_text_in_a_box from invenio_base.globals import cfg print(" [ERROR]") print( wrap_text_in_a_box( """\ DATABASE CONNECTIVITY ERROR: %(errmsg)s.\n Perhaps you need to set up database and connection rights? If yes, then please execute: console> inveniomanage database init --yes-i-know The values printed above were detected from your configuration. If they are not right, then please edit your instance configuration file (invenio.cfg). If the problem is of different nature, then please inspect the above error message and fix the problem before continuing.""" % { 'errmsg': err.args[0], 'dbname': cfg['CFG_DATABASE_NAME'], 'dbhost': cfg['CFG_DATABASE_HOST'], 'dbport': cfg['CFG_DATABASE_PORT'], 'dbuser': cfg['CFG_DATABASE_USER'], 'dbpass': cfg['CFG_DATABASE_PASS'], 'webhost': (cfg['CFG_DATABASE_HOST'] == 'localhost' and 'localhost' or os.popen('hostname -f', 'r').read().strip()), })) sys.exit(1) print(" [OK]")
def init(user='******', password='', yes_i_know=False): """Initialize database and user.""" from invenio_ext.sqlalchemy.utils import initialize_database_user from invenio_utils.text import wrap_text_in_a_box, wait_for_user from sqlalchemy_utils.functions import database_exists, create_database, \ drop_database from sqlalchemy.engine.url import URL from sqlalchemy import create_engine # Step 0: confirm deletion wait_for_user( wrap_text_in_a_box( "WARNING: You are going to destroy your database tables! Run first" " `inveniomanage database drop`.")) # Step 1: create URI to connect admin user cfg = current_app.config SQLALCHEMY_DATABASE_URI = URL( cfg.get('CFG_DATABASE_TYPE', 'mysql'), username=user, password=password, host=cfg.get('CFG_DATABASE_HOST'), database=cfg.get('CFG_DATABASE_NAME'), port=cfg.get('CFG_DATABASE_PORT'), ) # Step 2: drop the database if already exists if database_exists(SQLALCHEMY_DATABASE_URI): drop_database(SQLALCHEMY_DATABASE_URI) print('>>> Database has been dropped.') # Step 3: create the database create_database(SQLALCHEMY_DATABASE_URI, encoding='utf8') print('>>> Database has been created.') # Step 4: setup connection with special user engine = create_engine(SQLALCHEMY_DATABASE_URI) engine.connect() # Step 5: grant privileges for the user initialize_database_user( engine=engine, database_name=current_app.config['CFG_DATABASE_NAME'], database_user=current_app.config['CFG_DATABASE_USER'], database_pass=current_app.config['CFG_DATABASE_PASS'], ) print('>>> Database user has been initialized.')
def test_sqla_connection(): """Test connection with the database.""" print("Test connection... \t", end="") try: from sqlalchemy import inspect from invenio_ext.sqlalchemy import db inspector = inspect(db.engine) inspector.get_table_names() except OperationalError as err: from invenio_utils.text import wrap_text_in_a_box from invenio.config import CFG_DATABASE_HOST, \ CFG_DATABASE_PORT, CFG_DATABASE_NAME, CFG_DATABASE_USER, \ CFG_DATABASE_PASS print(" [ERROR]") print(wrap_text_in_a_box("""\ DATABASE CONNECTIVITY ERROR: %(errmsg)s.\n Perhaps you need to set up database and connection rights? If yes, then please execute: console> inveniomanage database init --yes-i-know The values printed above were detected from your configuration. If they are not right, then please edit your instance configuration file (invenio.cfg). If the problem is of different nature, then please inspect the above error message and fix the problem before continuing.""" % { 'errmsg': err.args[0], 'dbname': CFG_DATABASE_NAME, 'dbhost': CFG_DATABASE_HOST, 'dbport': CFG_DATABASE_PORT, 'dbuser': CFG_DATABASE_USER, 'dbpass': CFG_DATABASE_PASS, 'webhost': (CFG_DATABASE_HOST == 'localhost' and 'localhost' or os.popen('hostname -f', 'r').read().strip()), })) sys.exit(1) print(" [OK]")
def create_config(force=False, no_ssl=False): """ Create Apache configuration files for this site, keeping previous files in a backup copy. """ import os import pwd import pkg_resources import sys import shutil from flask import current_app from jinja2 import TemplateNotFound from invenio_ext.template import render_template_to_string from invenio_utils.text import wrap_text_in_a_box CFG_ETCDIR = current_app.config.get("CFG_ETCDIR", "") def get_context(): conf = current_app.config # Apache vhost conf file is distro specific, so analyze needs: # Gentoo (and generic defaults): listen_directive_needed = True ssl_pem_directive_needed = False ssl_pem_path = CFG_ETCDIR + "/apache/ssl/apache.pem" ssl_crt_path = CFG_ETCDIR + "/apache/ssl/server.crt" ssl_key_path = CFG_ETCDIR + "/apache/ssl/server.key" vhost_ip_address_needed = False wsgi_socket_directive_needed = False # Debian: if os.path.exists(os.path.sep + "etc" + os.path.sep + "debian_version"): listen_directive_needed = False ssl_pem_directive_needed = True ssl_pem_path = "/etc/apache2/ssl/apache.pem" ssl_crt_path = "/etc/apache2/ssl/server.crt" ssl_key_path = "/etc/apache2/ssl/server.key" # RHEL/SLC: if os.path.exists(os.path.sep + "etc" + os.path.sep + "redhat-release"): listen_directive_needed = False ssl_crt_path = "/etc/pki/tls/certs/localhost.crt" ssl_key_path = "/etc/pki/tls/private/localhost.key" vhost_ip_address_needed = True wsgi_socket_directive_needed = True # maybe we are using non-standard ports? vhost_site_url = conf.get("CFG_SITE_URL").replace("http://", "") if vhost_site_url.startswith("https://"): # The installation is configured to require HTTPS for any # connection vhost_site_url = vhost_site_url.replace("https://", "") vhost_site_url_port = "80" vhost_site_secure_url = conf.get("CFG_SITE_SECURE_URL").replace("https://", "").replace("http://", "") vhost_site_secure_url_port = "443" if ":" in vhost_site_url: vhost_site_url, vhost_site_url_port = vhost_site_url.split(":", 1) if ":" in vhost_site_secure_url: vhost_site_secure_url, vhost_site_secure_url_port = vhost_site_secure_url.split(":", 1) if vhost_site_url_port != "80" or vhost_site_secure_url_port != "443": listen_directive_needed = True static_root = current_app.config["COLLECT_STATIC_ROOT"] if not os.path.exists(static_root): os.mkdir(static_root) def prepare_alias(filename): if os.path.isdir(os.path.join(static_root, filename)): return "/%s/" % (filename,) return "/%s" % (filename,) aliases = map(prepare_alias, os.listdir(static_root)) apc1 = { "vhost_site_url_port": vhost_site_url_port, "servername": vhost_site_url, "serveralias": vhost_site_url.split(".")[0], "vhost_ip_address": vhost_ip_address_needed and _detect_ip_address() or "*", "wsgi_socket_directive_needed": wsgi_socket_directive_needed, "listen_directive_needed": listen_directive_needed, "aliases": aliases, } apc2 = { "vhost_site_url_port": vhost_site_secure_url_port, "servername": vhost_site_secure_url, "serveralias": vhost_site_secure_url.split(".")[0], "vhost_ip_address": vhost_ip_address_needed and _detect_ip_address() or "*", "wsgi_socket_directive_needed": wsgi_socket_directive_needed, "ssl_pem_directive": ssl_pem_directive_needed and "SSLCertificateFile %s" % ssl_pem_path or "#SSLCertificateFile %s" % ssl_pem_path, "ssl_crt_directive": ssl_pem_directive_needed and "#SSLCertificateFile %s" % ssl_crt_path or "SSLCertificateFile %s" % ssl_crt_path, "ssl_key_directive": ssl_pem_directive_needed and "#SSLCertificateKeyFile %s" % ssl_key_path or "SSLCertificateKeyFile %s" % ssl_key_path, "listen_directive_needed": listen_directive_needed, "aliases": aliases, } return [apc1, apc2] current_app.config.update( SYS_PREFIX=sys.prefix, CFG_RUNNING_AS_USER=pwd.getpwuid(os.getuid())[0], CFG_WSGIDIR=os.path.abspath(pkg_resources.resource_filename("invenio", "")), ) apache_conf_dir = current_app.instance_path + os.sep + "apache" print(">>> Going to create Apache conf files...") conf_files = ["invenio-apache-vhost.conf", "invenio-apache-vhost-ssl.conf"] conf_files = conf_files[: 1 if no_ssl else 2] if not os.path.exists(apache_conf_dir): os.mkdir(apache_conf_dir) for local_file, context in zip(conf_files, get_context()[: 1 if no_ssl else 2]): print(">>> Writing %s ..." % local_file) try: apache_vhost_file = apache_conf_dir + os.sep + local_file if os.path.exists(apache_vhost_file): shutil.copy(apache_vhost_file, apache_vhost_file + ".OLD") with open(apache_vhost_file, "w") as f: out = render_template_to_string(local_file + ".tpl", os=os, **context) print(out, file=f) except TemplateNotFound: print("Could not find template %s".format(local_file), file=sys.stderr) print( wrap_text_in_a_box( """\ Apache virtual host configuration file(s) for your Invenio site was(were) created. Please check created file(s) and activate virtual host(s). For example, you can put the following include statements in your httpd.conf:\n %s Please see the INSTALL file for more details. """ % "\n\n".join( tuple( map( lambda x: "Include " + apache_conf_dir.encode("utf-8") + os.sep + x, list(conf_files[: 1 if no_ssl else 2]), ) ) ) ) ) print(">>> Apache conf files created.")
def create_config(force=False, no_ssl=False): """ Create Apache configuration files for this site, keeping previous files in a backup copy. """ import os import pwd import pkg_resources import sys import shutil from flask import current_app from jinja2 import TemplateNotFound from invenio_ext.template import render_template_to_string from invenio_utils.text import wrap_text_in_a_box CFG_ETCDIR = current_app.config.get('CFG_ETCDIR', '') def get_context(): conf = current_app.config # Apache vhost conf file is distro specific, so analyze needs: # Gentoo (and generic defaults): listen_directive_needed = True ssl_pem_directive_needed = False ssl_pem_path = CFG_ETCDIR + '/apache/ssl/apache.pem' ssl_crt_path = CFG_ETCDIR + '/apache/ssl/server.crt' ssl_key_path = CFG_ETCDIR + '/apache/ssl/server.key' vhost_ip_address_needed = False wsgi_socket_directive_needed = False # Debian: if os.path.exists(os.path.sep + 'etc' + os.path.sep + 'debian_version'): listen_directive_needed = False ssl_pem_directive_needed = True ssl_pem_path = '/etc/apache2/ssl/apache.pem' ssl_crt_path = '/etc/apache2/ssl/server.crt' ssl_key_path = '/etc/apache2/ssl/server.key' # RHEL/SLC: if os.path.exists(os.path.sep + 'etc' + os.path.sep + 'redhat-release'): listen_directive_needed = False ssl_crt_path = '/etc/pki/tls/certs/localhost.crt' ssl_key_path = '/etc/pki/tls/private/localhost.key' vhost_ip_address_needed = True wsgi_socket_directive_needed = True # maybe we are using non-standard ports? vhost_site_url = conf.get('CFG_SITE_URL').replace("http://", "") if vhost_site_url.startswith("https://"): # The installation is configured to require HTTPS for any # connection vhost_site_url = vhost_site_url.replace("https://", "") vhost_site_url_port = '80' vhost_site_secure_url = conf.get('CFG_SITE_SECURE_URL').replace( "https://", "").replace("http://", "") vhost_site_secure_url_port = '443' if ':' in vhost_site_url: vhost_site_url, vhost_site_url_port = vhost_site_url.split(':', 1) if ':' in vhost_site_secure_url: vhost_site_secure_url, vhost_site_secure_url_port = \ vhost_site_secure_url.split(':', 1) if vhost_site_url_port != '80' or vhost_site_secure_url_port != '443': listen_directive_needed = True static_root = current_app.config['COLLECT_STATIC_ROOT'] if not os.path.exists(static_root): os.mkdir(static_root) def prepare_alias(filename): if os.path.isdir(os.path.join(static_root, filename)): return '/%s/' % (filename, ) return '/%s' % (filename, ) aliases = map(prepare_alias, os.listdir(static_root)) apc1 = {'vhost_site_url_port': vhost_site_url_port, 'servername': vhost_site_url, 'serveralias': vhost_site_url.split('.')[0], 'vhost_ip_address': vhost_ip_address_needed and _detect_ip_address() or '*', 'wsgi_socket_directive_needed': wsgi_socket_directive_needed, 'listen_directive_needed': listen_directive_needed, 'aliases': aliases, } apc2 = {'vhost_site_url_port': vhost_site_secure_url_port, 'servername': vhost_site_secure_url, 'serveralias': vhost_site_secure_url.split('.')[0], 'vhost_ip_address': vhost_ip_address_needed and _detect_ip_address() or '*', 'wsgi_socket_directive_needed': wsgi_socket_directive_needed, 'ssl_pem_directive': ssl_pem_directive_needed and 'SSLCertificateFile %s' % ssl_pem_path or '#SSLCertificateFile %s' % ssl_pem_path, 'ssl_crt_directive': ssl_pem_directive_needed and '#SSLCertificateFile %s' % ssl_crt_path or 'SSLCertificateFile %s' % ssl_crt_path, 'ssl_key_directive': ssl_pem_directive_needed and '#SSLCertificateKeyFile %s' % ssl_key_path or 'SSLCertificateKeyFile %s' % ssl_key_path, 'listen_directive_needed': listen_directive_needed, 'aliases': aliases, } return [apc1, apc2] current_app.config.update( SYS_PREFIX=sys.prefix, CFG_RUNNING_AS_USER=pwd.getpwuid(os.getuid())[0], CFG_WSGIDIR=os.path.abspath( pkg_resources.resource_filename('invenio', ''))) apache_conf_dir = current_app.instance_path + os.sep + 'apache' print(">>> Going to create Apache conf files...") conf_files = ['invenio-apache-vhost.conf', 'invenio-apache-vhost-ssl.conf'] conf_files = conf_files[:1 if no_ssl else 2] if not os.path.exists(apache_conf_dir): os.mkdir(apache_conf_dir) for local_file, context in zip(conf_files, get_context()[:1 if no_ssl else 2]): print(">>> Writing %s ..." % local_file) try: apache_vhost_file = apache_conf_dir + os.sep + local_file if os.path.exists(apache_vhost_file): shutil.copy(apache_vhost_file, apache_vhost_file + '.OLD') with open(apache_vhost_file, 'w') as f: out = render_template_to_string(local_file + '.tpl', os=os, **context) print(out, file=f) except TemplateNotFound: print("Could not find template %s".format(local_file), file=sys.stderr) print(wrap_text_in_a_box("""\ Apache virtual host configuration file(s) for your Invenio site was(were) created. Please check created file(s) and activate virtual host(s). For example, you can put the following include statements in your httpd.conf:\n %s Please see the INSTALL file for more details. """ % '\n\n'.join(tuple(map( lambda x: "Include " + apache_conf_dir.encode('utf-8') + os.sep + x, list(conf_files[:1 if no_ssl else 2])))))) print(">>> Apache conf files created.")