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 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 pre_upgrade():
    """Check for potentially invalid revisions"""

    # Check for any inconsistent data
    missing_parents = list(db.engine.execute(
        """SELECT id, id_parent FROM bwlOBJECT WHERE id_parent NOT IN (SELECT id FROM bwlOBJECT)"""
    ))
    if missing_parents:
        warnings.warn("Inconsistent parent IDs in bwlOBJECT '{0}'".format(
            missing_parents
        ))
        try:
            wait_for_user("\nSetting all dangling parents to NULL? (Ctrl+C to stop)\n")
        except SystemExit:
            raise RuntimeError("Upgrade aborted by user.")
        for parent in missing_parents:
            db.engine.execute(
                """UPDATE bwlOBJECT SET id_parent=NULL WHERE id={0}""".format(parent[0])
            )

    dangling_logs = list(db.engine.execute(
        """SELECT id_object FROM bwlOBJECTLOGGING WHERE id_object NOT IN (SELECT id FROM bwlOBJECT)"""
    )) + list(db.engine.execute(
        """SELECT id_object FROM bwlWORKFLOWLOGGING WHERE id_object NOT IN (SELECT uuid FROM bwlWORKFLOW)"""
    ))
    if dangling_logs:
        warnings.warn("Inconsistent logs in bwlOBJECT/bwlWORKFLOW '{0}'".format(
            len(dangling_logs)
        ))
        try:
            wait_for_user("\nDelete all dangling logs? (Ctrl+C to stop)\n")
        except SystemExit:
            raise RuntimeError("Upgrade aborted by user.")
        db.engine.execute(
            """DELETE FROM bwlOBJECTLOGGING WHERE id_object NOT IN (SELECT id FROM bwlOBJECT)"""
        )
        db.engine.execute(
            """DELETE FROM bwlWORKFLOWLOGGING WHERE id_object NOT IN (SELECT uuid FROM bwlWORKFLOW)"""
        )