Beispiel #1
0
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)
Beispiel #2
0
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))
Beispiel #3
0
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]")
Beispiel #4
0
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.')
Beispiel #5
0
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]")
Beispiel #6
0
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.")
Beispiel #7
0
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.")