Example #1
0
def create_base_schema():
    log.info('Creating base schema')
    create_log.info("SCHEMA")

    # Functions
    functions = environ.find_resource('sql', 'functions.sql')
    if db_settings.execute_sql(functions) != 0:
        error(u'Failed to create functions')

    # A Base schema shared between all RDBMS implementations
    schema = _get_latest_schema()
    if db_settings.execute_sql(schema) != 0:
        error(u'Failed to create base schema')

    try:
        schema = environ.find_resource('sql',
                                       '%s-schema.sql' % db_settings.rdbms)
        if db_settings.execute_sql(schema) != 0:
            error(u'Failed to create %s specific schema' %
                  (db_settings.rdbms, ))
    except EnvironmentError:
        pass

    migration = StoqlibSchemaMigration()
    migration.apply_all_patches()
Example #2
0
def restore_database(user_hash, time=None):
    assert user_hash

    # If the database doesn't exist, get_default_store will fail
    try:
        default_store = get_default_store()
    except Exception:
        default_store = None

    if default_store is not None and db_settings.has_database():
        try:
            default_store.lock_database()
        except DatabaseError:
            raise TaskException(
                "Could not lock database. This means that there are other "
                "clients connected. Make sure to close every Stoq client "
                "before updating the database")
        except Exception:
            raise TaskException(
                "Database is empty or in a corrupted state. Fix or drop it "
                "before trying to proceed with the restore")
        else:
            default_store.unlock_database()

        # FIXME: Windows will not liberate resource for other process to
        # write to the file. We should write our own TemporaryFile on Stoq
        # that handles all those cases for us and use here
        with tempfile.NamedTemporaryFile(delete=False) as f:
            pass
        try:
            if not db_settings.dump_database(f.name):
                raise TaskException("Failed to dump the database")
            backup_name = db_settings.restore_database(f.name)
            logger.info("Created a backup of the current database state on %s",
                        backup_name)
        finally:
            os.unlink(f.name)

    tmp_path = tempfile.mkdtemp()
    try:
        restore_path = os.path.join(tmp_path, 'stoq')
        backup.restore(restore_path, user_hash, time=time)

        # None will make the default store be closed, which we need
        # to sucessfully restore the database
        set_default_store(None)
        db_settings.clean_database(db_settings.dbname, force=True)
        db_settings.execute_sql(os.path.join(restore_path, 'stoq.dump'),
                                lock_database=True)

        logger.info("Backup restore finished sucessfully")
    finally:
        # get_default_store will recreate it (since we closed it above)
        get_default_store()
        shutil.rmtree(tmp_path, ignore_errors=True)
Example #3
0
def restore_database(user_hash, time=None):
    assert user_hash

    # If the database doesn't exist, get_default_store will fail
    try:
        default_store = get_default_store()
    except Exception:
        default_store = None

    if default_store is not None and db_settings.has_database():
        try:
            default_store.lock_database()
        except DatabaseError:
            raise TaskException(
                "Could not lock database. This means that there are other "
                "clients connected. Make sure to close every Stoq client "
                "before updating the database")
        except Exception:
            raise TaskException(
                "Database is empty or in a corrupted state. Fix or drop it "
                "before trying to proceed with the restore")
        else:
            default_store.unlock_database()

        # FIXME: Windows will not liberate resource for other process to
        # write to the file. We should write our own TemporaryFile on Stoq
        # that handles all those cases for us and use here
        with tempfile.NamedTemporaryFile(delete=False) as f:
            pass
        try:
            if not db_settings.dump_database(f.name):
                raise TaskException("Failed to dump the database")
            backup_name = db_settings.restore_database(f.name)
            logger.info("Created a backup of the current database state on %s",
                        backup_name)
        finally:
            os.unlink(f.name)

    tmp_path = tempfile.mkdtemp()
    try:
        restore_path = os.path.join(tmp_path, 'stoq')
        logger.info("restoring database to %s", restore_path)
        backup.restore(restore_path, user_hash, time=time)

        # None will make the default store be closed, which we need
        # to sucessfully restore the database
        set_default_store(None)
        db_settings.clean_database(db_settings.dbname, force=True)
        db_settings.execute_sql(os.path.join(restore_path, 'stoq.dump'),
                                lock_database=True)

        logger.info("Backup restore finished sucessfully")
    finally:
        # get_default_store will recreate it (since we closed it above)
        get_default_store()
Example #4
0
def restore_database(user_hash, time=None):
    assert user_hash

    # If the database doesn't exist, get_default_store will fail
    try:
        default_store = get_default_store()
    except Exception:
        default_store = None

    if default_store is not None and db_settings.has_database():
        try:
            default_store.lock_database()
        except DatabaseError:
            raise TaskException(
                "Could not lock database. This means that there are other "
                "clients connected. Make sure to close every Stoq client "
                "before updating the database")
        except Exception:
            raise TaskException(
                "Database is empty or in a corrupted state. Fix or drop it "
                "before trying to proceed with the restore")
        else:
            default_store.unlock_database()

        with tempfile.NamedTemporaryFile() as f:
            if not db_settings.dump_database(f.name):
                raise TaskException("Failed to dump the database")
            backup_name = db_settings.restore_database(f.name)
            logger.info("Created a backup of the current database state on %s",
                        backup_name)

    tmp_path = tempfile.mkdtemp()
    try:
        # None will make the default store be closed, which we need
        # to sucessfully restore the database
        set_default_store(None)
        restore_path = os.path.join(tmp_path, 'stoq')

        backup.restore(restore_path, user_hash, time=time)

        db_settings.clean_database(db_settings.dbname, force=True)
        db_settings.execute_sql(os.path.join(restore_path, 'stoq.dump'),
                                lock_database=True)

        logger.info("Backup restore finished sucessfully")
    finally:
        # get_default_store will recreate it (since we closed it above)
        get_default_store()
        shutil.rmtree(tmp_path, ignore_errors=True)
Example #5
0
def create_database_functions():
    """Create some functions we define on the database

    This will simply read data/sql/functions.sql and execute it
    """
    with tempfile.NamedTemporaryFile(suffix='stoqfunctions-') as tmp_f:
        functions = environ.get_resource_string('stoq', 'sql', 'functions.sql')
        tmp_f.write(render_template_string(functions))
        tmp_f.flush()
        if db_settings.execute_sql(tmp_f.name) != 0:
            error(u'Failed to create functions')
Example #6
0
def create_base_schema():
    log.info('Creating base schema')
    create_log.info("SCHEMA")

    create_database_functions()

    # A Base schema shared between all RDBMS implementations
    schema = _get_latest_schema()
    if db_settings.execute_sql(schema) != 0:
        error(u'Failed to create base schema')

    try:
        schema = environ.find_resource('sql', '%s-schema.sql' % db_settings.rdbms)
        if db_settings.execute_sql(schema) != 0:
            error(u'Failed to create %s specific schema' % (db_settings.rdbms, ))
    except EnvironmentError:
        pass

    migration = StoqlibSchemaMigration()
    migration.apply_all_patches()
Example #7
0
def create_database_functions():
    """Create some functions we define on the database

    This will simply read data/sql/functions.sql and execute it
    """
    with tempfile.NamedTemporaryFile(suffix='stoqfunctions-') as tmp_f:
        with open(environ.find_resource('sql', 'functions.sql')) as f:
            tmp_f.write(render_template_string(f.read()))
            tmp_f.flush()
        if db_settings.execute_sql(tmp_f.name) != 0:
            error(u'Failed to create functions')
Example #8
0
def create_database_functions():
    """Create some functions we define on the database

    This will simply read data/sql/functions.sql and execute it
    """
    # We cant remove the file, otherwise it will fail on windows.
    with tempfile.NamedTemporaryFile(prefix='stoqfunctions-', delete=False) as tmp_f:
        functions = pkg_resources.resource_string('stoq', 'sql/functions.sql')
        tmp_f.write(render_template_string(functions))
        tmp_f.flush()
        if db_settings.execute_sql(tmp_f.name) != 0:
            error(u'Failed to create functions')
Example #9
0
def create_database_functions():
    """Create some functions we define on the database

    This will simply read data/sql/functions.sql and execute it
    """
    # We cant remove the file, otherwise it will fail on windows.
    with tempfile.NamedTemporaryFile(prefix='stoqfunctions-', delete=False) as tmp_f:
        functions = environ.get_resource_string('stoq', 'sql', 'functions.sql')
        tmp_f.write(render_template_string(functions))
        tmp_f.flush()
        if db_settings.execute_sql(tmp_f.name) != 0:
            error(u'Failed to create functions')
Example #10
0
def populate_initial_data(store):
    from stoqlib.domain.system import SystemTable
    generation = store.find(SystemTable).max(SystemTable.generation)
    if generation < 4:
        # FIXME: Initial data can (and needs to) only be sourced on schemas
        #        greater or equal than 4. Remove this in the future.
        return

    log.info('Populating initial data')
    initial_data = pkg_resources.resource_filename('stoq', 'sql/initial.sql')
    if db_settings.execute_sql(initial_data) != 0:
        error(u'Failed to populate initial data')
Example #11
0
File: admin.py Project: romaia/stoq
def populate_initial_data(store):
    from stoqlib.domain.system import SystemTable
    generation = store.find(SystemTable).max(SystemTable.generation)
    if generation < 4:
        # FIXME: Initial data can (and needs to) only be sourced on schemas
        #        greater or equal than 4. Remove this in the future.
        return

    log.info('Populating initial data')
    initial_data = environ.find_resource('sql', 'initial.sql')
    if db_settings.execute_sql(initial_data) != 0:
        error(u'Failed to populate initial data')
Example #12
0
    def apply(self, store):
        """Apply the patch
        :param store: a store
        """

        # Dont lock the database here, since StoqlibSchemaMigration.update has
        # already did that before starting to apply the patches

        # SQL statement to update the system_table
        sql = self._migration.generate_sql_for_patch(self)

        if self.filename.endswith('.sql'):
            # Create a temporary file used for writing SQL statements
            temporary = tempfile.mktemp(prefix="patch-%d-%d-" %
                                        self.get_version())

            # Overwrite the temporary file with the sql patch we want to apply
            shutil.copy(self.filename, temporary)

            # After successfully executing the SQL statements, we need to
            # make sure that the system_table is updated with the correct
            # schema generation and patchlevel
            open(temporary, 'a').write(sql)

            retcode = db_settings.execute_sql(temporary)
            if retcode != 0:
                error('Failed to apply %s, psql returned error code: %d' %
                      (os.path.basename(self.filename), retcode))

            os.unlink(temporary)
        elif self.filename.endswith('.py'):
            # Execute the patch, we cannot use __import__() since there are
            # hyphens in the filename and data/sql lacks an __init__.py
            ns = {}
            exec(compile(open(self.filename).read(), self.filename, 'exec'),
                 ns, ns)
            function = ns['apply_patch']

            # Create a new store that will be used to apply the patch and
            # to update the system tables after the patch has been successfully
            # applied
            patch_store = new_store()

            # Apply the patch itself
            function(patch_store)

            # After applying the patch, update the system_table within the same
            # transaction
            patch_store.execute(sql)
            patch_store.commit(close=True)
        else:
            raise AssertionError("Unknown filename: %s" % (self.filename, ))
Example #13
0
def create_base_schema():
    log.info('Creating base schema')
    create_log.info("SCHEMA")

    create_database_functions()

    # A Base schema shared between all RDBMS implementations
    schema = _get_latest_schema()
    if db_settings.execute_sql(schema) != 0:
        error(u'Failed to create base schema')

    migration = StoqlibSchemaMigration()
    migration.apply_all_patches()
Example #14
0
def create_base_schema():
    log.info('Creating base schema')
    create_log.info("SCHEMA")

    create_database_functions()

    # A Base schema shared between all RDBMS implementations
    schema = _get_latest_schema()
    if db_settings.execute_sql(schema) != 0:
        error(u'Failed to create base schema')

    migration = StoqlibSchemaMigration()
    migration.apply_all_patches()
Example #15
0
    def apply(self, store):
        """Apply the patch
        :param store: a store
        """

        # Dont lock the database here, since StoqlibSchemaMigration.update has
        # already did that before starting to apply the patches

        # SQL statement to update the system_table
        sql = self._migration.generate_sql_for_patch(self)

        if self.filename.endswith('.sql'):
            # Create a temporary file used for writing SQL statements
            temporary = tempfile.mktemp(prefix="patch-%d-%d-" % self.get_version())

            # Overwrite the temporary file with the sql patch we want to apply
            shutil.copy(self.filename, temporary)

            # After successfully executing the SQL statements, we need to
            # make sure that the system_table is updated with the correct
            # schema generation and patchlevel
            open(temporary, 'a').write(sql)

            retcode = db_settings.execute_sql(temporary)
            if retcode != 0:
                error('Failed to apply %s, psql returned error code: %d' % (
                    os.path.basename(self.filename), retcode))

            os.unlink(temporary)
        elif self.filename.endswith('.py'):
            # Execute the patch, we cannot use __import__() since there are
            # hyphens in the filename and data/sql lacks an __init__.py
            ns = {}
            execfile(self.filename, ns, ns)
            function = ns['apply_patch']

            # Create a new store that will be used to apply the patch and
            # to update the system tables after the patch has been successfully
            # applied
            patch_store = new_store()

            # Apply the patch itself
            function(patch_store)

            # After applying the patch, update the system_table within the same
            # transaction
            patch_store.execute(sql)
            patch_store.commit(close=True)
        else:
            raise AssertionError("Unknown filename: %s" % (self.filename, ))
Example #16
0
    def _update_schema(self):
        """Check the current version of database and update the schema if
        it's needed
        """
        log.info("Updating schema")

        if self.check_uptodate():
            log.info("Schema is already up to date")
            return

        patches = self._get_patches()
        latest_available = patches[-1].get_version()
        current_version = self.get_current_version()

        last_level = None
        if current_version != latest_available:
            patches_to_apply = []
            for patch in patches:
                if patch.get_version() <= current_version:
                    continue
                patches_to_apply.append(patch)

            functions = environ.get_resource_filename('stoq', 'sql',
                                                      'functions.sql')
            if db_settings.execute_sql(functions) != 0:
                error('Failed to create functions')

            log.info("Applying %d patches" % (len(patches_to_apply), ))
            create_log.info("PATCHES:%d" % (len(patches_to_apply), ))

            for patch in patches_to_apply:
                create_log.info("PATCH:%d.%d" %
                                (patch.generation, patch.level))
                patch.apply(self.default_store)

            assert patches_to_apply
            log.info("All patches (%s) applied." %
                     (', '.join(str(p.level) for p in patches_to_apply)))
            last_level = patches_to_apply[-1].get_version()

        self.after_update()

        return current_version, last_level
Example #17
0
    def _update_schema(self):
        """Check the current version of database and update the schema if
        it's needed
        """
        log.info("Updating schema")

        if self.check_uptodate():
            log.info("Schema is already up to date")
            return

        patches = self._get_patches()
        latest_available = patches[-1].get_version()
        current_version = self.get_current_version()

        last_level = None
        if current_version != latest_available:
            patches_to_apply = []
            for patch in patches:
                if patch.get_version() <= current_version:
                    continue
                patches_to_apply.append(patch)

            functions = environ.get_resource_filename('stoq', 'sql', 'functions.sql')
            if db_settings.execute_sql(functions) != 0:
                error('Failed to create functions')

            log.info("Applying %d patches" % (len(patches_to_apply), ))
            create_log.info("PATCHES:%d" % (len(patches_to_apply), ))

            for patch in patches_to_apply:
                create_log.info("PATCH:%d.%d" % (patch.generation,
                                                 patch.level))
                patch.apply(self.default_store)

            assert patches_to_apply
            log.info("All patches (%s) applied." % (
                ', '.join(str(p.level) for p in patches_to_apply)))
            last_level = patches_to_apply[-1].get_version()

        self.after_update()

        return current_version, last_level