def _drop_database(self):
        sql = """\
            SELECT 'DROP PUBLIC SYNONYM ' || SYNONYM_NAME ||';' FROM ALL_SYNONYMS \
            WHERE OWNER = 'PUBLIC' AND TABLE_OWNER = '%s' \
            UNION ALL \
            SELECT 'DROP SYNONYM ' || SYNONYM_NAME ||';' FROM ALL_SYNONYMS \
            WHERE OWNER = '%s' AND TABLE_OWNER = '%s' \
            UNION ALL \
            SELECT 'DROP ' || OBJECT_TYPE || ' ' || OBJECT_NAME ||';'   FROM USER_OBJECTS \
            WHERE OBJECT_TYPE <> 'TABLE' AND OBJECT_TYPE <> 'INDEX' AND \
            OBJECT_TYPE<>'TRIGGER'  AND OBJECT_TYPE<>'LOB' \
            UNION ALL \
            SELECT 'DROP ' || OBJECT_TYPE || ' ' || OBJECT_NAME ||' CASCADE CONSTRAINTS;'   FROM USER_OBJECTS \
            WHERE OBJECT_TYPE = 'TABLE' AND OBJECT_NAME NOT LIKE 'BIN$%%'""" % (self.__user.upper(), self.__user.upper(), self.__user.upper())

        conn = self.__connect()
        cursor = conn.cursor()
        try:
            cursor.execute(sql)
            rows = cursor.fetchall()

            failed_sqls = ''
            for row in rows:
                drop_sql = row[0]
                try:
                    self.__execute(drop_sql)
                except Exception, e:
                    failed_sqls = failed_sqls + "can't execute drop command '%s' in database '%s', %s\n" % (drop_sql, self.__db, str(e).strip())

            if failed_sqls != '':
                CLI.msg('\nThe following drop commands failed:\n%s' % (failed_sqls), "RED")
                CLI.msg('\nDo you want to continue anyway (y/N):', "END")
                to_continue = self.std_in.readline().strip()
                if to_continue.upper() != 'Y':
                    raise Exception("can't drop database objects for user '%s'" % (self.__user) )
Exemple #2
0
 def _verify_if_exception_is_invalid_user(self, exception):
     import pdb
     pdb.set_trace()
     #TODO validar como isso funciona no mongodb
     if 'ORA-01017' in exception.__str__():
         try:
             cli = CLI()
             cli.msg(
                 '\nPlease inform dba user/password to connect to database "%s"\nUser:'
                 % (self.__host), "END")
             dba_user = self.std_in.readline().strip()
             passwd = self.get_pass()
             conn = self.__driver.connect(dsn=self.__host,
                                          user=dba_user,
                                          password=passwd)
             cursor = conn.cursor()
             cursor.execute("create user %s identified by %s" %
                            (self.__user, self.__passwd))
             cursor.execute("grant connect, resource to %s" % (self.__user))
             cursor.execute("grant create public synonym to %s" %
                            (self.__user))
             cursor.execute("grant drop public synonym to %s" %
                            (self.__user))
             cursor.close()
             conn.close()
         except Exception, e:
             raise Exception("check error: %s" % e)
Exemple #3
0
    def _drop_database(self):
        sql = """\
            SELECT 'DROP PUBLIC SYNONYM ' || SYNONYM_NAME ||';' FROM ALL_SYNONYMS \
            WHERE OWNER = 'PUBLIC' AND TABLE_OWNER = '%s' \
            UNION ALL \
            SELECT 'DROP SYNONYM ' || SYNONYM_NAME ||';' FROM ALL_SYNONYMS \
            WHERE OWNER = '%s' AND TABLE_OWNER = '%s' \
            UNION ALL \
            SELECT 'DROP ' || OBJECT_TYPE || ' ' || OBJECT_NAME ||';'   FROM USER_OBJECTS \
            WHERE OBJECT_TYPE <> 'TABLE' AND OBJECT_TYPE <> 'INDEX' AND \
            OBJECT_TYPE<>'TRIGGER'  AND OBJECT_TYPE<>'LOB' \
            UNION ALL \
            SELECT 'DROP ' || OBJECT_TYPE || ' ' || OBJECT_NAME ||' CASCADE CONSTRAINTS;'   FROM USER_OBJECTS \
            WHERE OBJECT_TYPE = 'TABLE' AND OBJECT_NAME NOT LIKE 'BIN$%%'""" % (self.__user.upper(), self.__user.upper(), self.__user.upper())

        conn = self.__connect()
        cursor = conn.cursor()
        try:
            cursor.execute(sql)
            rows = cursor.fetchall()

            failed_sqls = ''
            for row in rows:
                drop_sql = row[0]
                try:
                    self.__execute(drop_sql)
                except Exception, e:
                    failed_sqls = failed_sqls + "can't execute drop command '%s' in database '%s', %s\n" % (drop_sql, self.__db, str(e).strip())

            if failed_sqls != '':
                CLI.msg('\nThe following drop commands failed:\n%s' % (failed_sqls), "RED")
                CLI.msg('\nDo you want to continue anyway (y/N):', "END")
                to_continue = self.std_in.readline().strip()
                if to_continue.upper() != 'Y':
                    raise Exception("can't drop database '%s'" % (self.__db) )
Exemple #4
0
def run():
    cli = CLI()
    try:
        (options, args) = cli.parse()

        if options.simple_db_migrate_version:
            msg = 'simple-db-migrate v%s' % SIMPLE_DB_MIGRATE_VERSION
            cli.info_and_exit(msg)

        if options.show_colors:
            CLI.show_colors()

        # Create config
        config = FileConfig(options.config_file, options.environment)
        config.put('schema_version', options.schema_version)
        config.put('show_sql', options.show_sql)
        config.put('show_sql_only', options.show_sql_only)
        config.put('new_migration', options.new_migration)
        config.put('drop_db_first', options.drop_db_first)
        config.put('paused_mode', options.paused_mode)
        config.put('log_dir', options.log_dir)
        config.put('label_version', options.label_version)
        config.put('force_use_files_on_down', options.force_use_files_on_down)
        config.put('force_execute_old_migrations_versions',
                   options.force_execute_old_migrations_versions)

        # paused mode forces log_level to 2
        log_level = int(options.log_level)
        if options.paused_mode:
            log_level = 2

        config.put('log_level', log_level)

        # Ask the password for user if configured
        if config.get('db_password') == '<<ask_me>>':
            if options.password:
                passwd = options.password
            else:
                cli.msg(
                    '\nPlease inform password to connect to database "%s@%s:%s"'
                    % (config.get('db_user'), config.get('db_host'),
                       config.get('db_name')))
                passwd = getpass()
            config.remove('db_password')
            config.put('db_password', passwd)

        # If CLI was correctly parsed, execute db-migrate.
        Main(config).execute()
    except KeyboardInterrupt:
        cli.info_and_exit("\nExecution interrupted by user...")
    except Exception, e:
        cli.error_and_exit(str(e))
Exemple #5
0
 def _verify_if_exception_is_invalid_user(self, exception):
     if 'ORA-01017' in exception.__str__():
         CLI.msg('\nPlease inform dba user/password to connect to database "%s"\nUser:' % (self.__host), "END")
         dba_user = self.std_in.readline().strip()
         passwd = self.get_pass()
         conn = self.__driver.connect(dsn=self.__host, user=dba_user, password=passwd)
         cursor = conn.cursor()
         try:
             cursor.execute("create user %s identified by %s" % (self.__user, self.__passwd))
             cursor.execute("grant connect, resource to %s" % (self.__user))
             cursor.execute("grant create public synonym to %s" % (self.__user))
             cursor.execute("grant drop public synonym to %s" % (self.__user))
         except Exception, e:
             raise Exception("check error: %s" % e)
         finally:
 def _verify_if_exception_is_invalid_user(self, exception):
     if 'ORA-01017' in exception.__str__():
         CLI.msg('\nPlease inform dba user/password to connect to database "%s"\nUser:' % (self.__host), "END")
         dba_user = self.std_in.readline().strip()
         passwd = self.get_pass()
         conn = self.__driver.connect(dsn=self.__host, user=dba_user, password=passwd)
         cursor = conn.cursor()
         try:
             cursor.execute("create user %s identified by %s" % (self.__user, self.__passwd))
             cursor.execute("grant connect, resource to %s" % (self.__user))
             cursor.execute("grant create public synonym to %s" % (self.__user))
             cursor.execute("grant drop public synonym to %s" % (self.__user))
         except Exception, e:
             raise Exception("check error: %s" % e)
         finally:
Exemple #7
0
def run():
    cli = CLI()
    try:
        (options, args) = cli.parse()

        if options.simple_db_migrate_version:
            msg = 'simple-db-migrate v%s' % SIMPLE_DB_MIGRATE_VERSION
            cli.info_and_exit(msg)

        if options.show_colors:
            CLI.show_colors()

        # Create config
        config = FileConfig(options.config_file, options.environment)
        config.put('schema_version', options.schema_version)
        config.put('show_sql', options.show_sql)
        config.put('show_sql_only', options.show_sql_only)
        config.put('new_migration', options.new_migration)
        config.put('drop_db_first', options.drop_db_first)
        config.put('paused_mode', options.paused_mode)
        config.put('log_dir', options.log_dir)
        config.put('label_version', options.label_version)
        config.put('force_use_files_on_down', options.force_use_files_on_down)
        config.put('force_execute_old_migrations_versions', options.force_execute_old_migrations_versions)

        # paused mode forces log_level to 2
        log_level = int(options.log_level)
        if options.paused_mode:
            log_level = 2

        config.put('log_level', log_level)

        # Ask the password for user if configured
        if config.get('db_password') == '<<ask_me>>':
            if options.password:
                passwd = options.password
            else:
                cli.msg('\nPlease inform password to connect to database "%s@%s:%s"' % (config.get('db_user'), config.get('db_host'), config.get('db_name')))
                passwd = getpass()
            config.remove('db_password')
            config.put('db_password', passwd)

        # If CLI was correctly parsed, execute db-migrate.
        Main(config).execute()
    except KeyboardInterrupt:
        cli.info_and_exit("\nExecution interrupted by user...")
    except Exception, e:
        cli.error_and_exit(str(e))
Exemple #8
0
 def _verify_if_exception_is_invalid_user(self, exception):
     import pdb;pdb.set_trace()
     #TODO validar como isso funciona no mongodb
     if 'ORA-01017' in exception.__str__():
         try:
             cli = CLI()
             cli.msg('\nPlease inform dba user/password to connect to database "%s"\nUser:' % (self.__host), "END")
             dba_user = self.std_in.readline().strip()
             passwd = self.get_pass()
             conn = self.__driver.connect(dsn=self.__host, user=dba_user, password=passwd)
             cursor = conn.cursor()
             cursor.execute("create user %s identified by %s" % (self.__user, self.__passwd))
             cursor.execute("grant connect, resource to %s" % (self.__user))
             cursor.execute("grant create public synonym to %s" % (self.__user))
             cursor.execute("grant drop public synonym to %s" % (self.__user))
             cursor.close()
             conn.close()
         except Exception, e:
             raise Exception("check error: %s" % e)
Exemple #9
0
class Main(object):

    def __init__(self, config=None, mysql=None, db_migrate=None):
        self.cli = CLI()
        self.config = config or {}

        self.mysql = mysql
        if self.mysql is None and not self.config.get("new_migration"):
            self.mysql = MySQL(config)

        self.db_migrate = db_migrate or SimpleDBMigrate(config)

    def execute(self):
        self.cli.msg("\nStarting DB migration...", "PINK")
        if self.config.get("new_migration"):
            self.create_migration()
        else:
            self.migrate()
        self.cli.msg("\nDone.\n", "PINK")

    def create_migration(self):
        # TODO: create file in the migrations directory, not in current
        new_file = Migration.create(self.config.get("new_migration"))
        self.cli.msg("- Created file '%s'" % (new_file))

    def migrate(self):
        destination_version = self.get_destination_version()
        current_version = self.mysql.get_current_schema_version()

        self.cli.msg("- Current version is: %s" % current_version, "GREEN")
        self.cli.msg("- Destination version is: %s" % destination_version, "GREEN")

        # if current and destination versions are the same,
        # will consider a migration up to execute remaining files
        is_migration_up = True
        if int(current_version) > int(destination_version):
            is_migration_up = False

        # do it!
        self.execute_migrations(current_version, destination_version, is_migration_up)

    def get_destination_version(self):
        destination_version = self.config.get("schema_version")
        if destination_version is None:
            destination_version = self.db_migrate.latest_version_available()

        if destination_version is not '0' and not self.db_migrate.check_if_version_exists(destination_version):
            raise Exception("version not found (%s)" % destination_version)

        return destination_version

    def get_migration_files_to_be_executed(self, current_version, destination_version):
        mysql_versions = self.mysql.get_all_schema_versions()
        migration_versions = self.db_migrate.get_all_migration_versions()

        # migration up: the easy part
        if current_version <= destination_version:
            remaining_versions_to_execute = Lists.subtract(migration_versions, mysql_versions)
            remaining_versions_to_execute = [version for version in remaining_versions_to_execute if version <= destination_version]
            return remaining_versions_to_execute

        # migration down...
        down_versions = [version for version in mysql_versions if version <= current_version and version > destination_version]
        for version in down_versions:
            if version not in migration_versions:
                raise Exception("impossible to migrate down: one of the versions was not found (%s)" % version)
        down_versions.reverse()
        return down_versions

    def execute_migrations(self, current_version, destination_version, is_migration_up):
        # getting only the migration sql files to be executed
        versions_to_be_executed = self.get_migration_files_to_be_executed(current_version, destination_version)

        if versions_to_be_executed is None or len(versions_to_be_executed) == 0:
            self.cli.msg("\nNothing to do.\n", "PINK")
            return

        up_down_label = is_migration_up and "up" or "down"
        if self.config.get("show_sql_only"):
            self.cli.msg("\nWARNING: database migrations are not being executed ('--showsqlonly' activated)", "YELLOW")
        else:
            self.cli.msg("\nStarting migration %s!" % up_down_label)
        
        if self.config.get("log_level") >= 1:
            self.cli.msg("*** versions: %s\n" % versions_to_be_executed, "CYAN")

        sql_statements_executed = []
        for migration_version in versions_to_be_executed:
            migration = self.db_migrate.get_migration_from_version_number(migration_version)
            sql = is_migration_up and migration.sql_up or migration.sql_down

            if not self.config.get("show_sql_only"):
                if self.config.get("log_level") >= 1:
                    self.cli.msg("===== executing %s (%s) =====" % (migration.file_name, up_down_label))
                
                log = None
                if self.config.get("log_level") >= 2:
                    log = self.cli.msg
                
                self.mysql.change(sql, migration_version, is_migration_up, execution_log=log)
                
                # paused mode
                if self.config.get("paused_mode"):
                    raw_input("* press <enter> to continue... ")

            # recording the last statement executed
            sql_statements_executed.append(sql)

        if self.config.get("show_sql") or self.config.get("show_sql_only"):
            self.cli.msg("__________ SQL statements executed __________", "YELLOW")
            for sql in sql_statements_executed:
                self.cli.msg(sql, "YELLOW")
            self.cli.msg("_____________________________________________", "YELLOW")
Exemple #10
0
 def _execution_log(self, msg, color="CYAN", log_level_limit=2):
     if self.config.get("log_level", 1) >= log_level_limit:
         CLI.msg(msg, color)
     self.log.debug(msg)
Exemple #11
0
class Main(object):
    def __init__(self, config=None, mysql=None, db_migrate=None):
        self.__cli = CLI()
        self.__config = config

        self.__mysql = mysql
        if self.__mysql is None and not self.__config.get("new_migration"):
            self.__mysql = MySQL(config)

        self.__db_migrate = db_migrate
        if self.__db_migrate is None:
            self.__db_migrate = Migrations(config)

    def execute(self):
        self.__cli.msg("\nStarting DB migration...", "PINK")
        if self.__config.get("new_migration"):
            self._create_migration()
        else:
            self._migrate()
        self.__cli.msg("\nDone.\n", "PINK")

    def _create_migration(self):
        new_file = self.__db_migrate.create_migration(self.__config.get("new_migration"))
        self.__cli.msg("- Created file '%s'" % (new_file))

    def _migrate(self):
        destination_version = self._get_destination_version()
        current_version = self.__mysql.get_current_schema_version()

        self.__cli.msg("- Current version is: %s" % current_version, "GREEN")
        self.__cli.msg("- Destination version is: %s" % destination_version, "GREEN")

        # if current and destination versions are the same,
        # will consider a migration up to execute remaining files
        is_migration_up = True
        if int(current_version) > int(destination_version):
            is_migration_up = False

        # do it!
        self._execute_migrations(current_version, destination_version, is_migration_up)

    def _get_destination_version(self):
        destination_version = self.__config.get("schema_version")
        if destination_version is None:
            destination_version = self.__db_migrate.latest_schema_version_available()

        if not self.__db_migrate.check_if_version_exists(destination_version):
            self.__cli.error_and_exit("version not found (%s)" % destination_version)

        return destination_version

    def _get_migration_files_to_be_executed(self, current_version, destination_version):
        mysql_versions = self.__mysql.get_all_schema_versions()
        migration_versions = self.__db_migrate.get_all_migration_versions()

        # migration up: the easy part
        if current_version <= destination_version:
            remaining_versions_to_execute = Lists.subtract(migration_versions, mysql_versions)
            remaining_versions_to_execute = [
                version for version in remaining_versions_to_execute if version <= destination_version
            ]
            return remaining_versions_to_execute

        # migration down...
        down_versions = [
            version for version in mysql_versions if version <= current_version and version > destination_version
        ]
        for version in down_versions:
            if version not in migration_versions:
                self.__cli.error_and_exit(
                    "impossible to migrate down: one of the versions was not found (%s)" % version
                )
        down_versions.reverse()
        return down_versions

    def _execute_migrations(self, current_version, destination_version, is_migration_up):
        # getting only the migration sql files to be executed
        versions_to_be_executed = self._get_migration_files_to_be_executed(current_version, destination_version)

        if versions_to_be_executed is None or len(versions_to_be_executed) == 0:
            self.__cli.msg("\nNothing to do.\n", "PINK")
            sys.exit(0)

        up_down_label = "up" if is_migration_up else "down"
        if self.__config.get("show_sql_only"):
            self.__cli.msg("WARNING: database migrations are not being executed ('--showsqlonly' activated)", "YELLOW")
        else:
            self.__cli.msg("\nStarting migration %s!" % up_down_label)

        self.__cli.msg("*** versions: %s\n" % versions_to_be_executed, "GRAY")

        sql_statements_executed = []
        for migration_version in versions_to_be_executed:
            sql_file = self.__db_migrate.get_migration_file_name_from_version_number(migration_version)
            sql = self.__db_migrate.get_sql_command(sql_file, is_migration_up)

            if not self.__config.get("show_sql_only"):
                self.__cli.msg("===== executing %s (%s) =====" % (sql_file, up_down_label))
                self.__mysql.change(sql, migration_version, is_migration_up)

            # recording the last statement executed
            sql_statements_executed.append(sql)

        if self.__config.get("show_sql") or self.__config.get("show_sql_only"):
            self.__cli.msg("__________ SQL statements executed __________", "YELLOW")
            for sql in sql_statements_executed:
                self.__cli.msg(sql, "YELLOW")
            self.__cli.msg("_____________________________________________", "YELLOW")
def run(options):
    """ Initial Module. Treat Parameters and call Main Module for execution """
    try:
        if options.get('simple_virtuoso_migrate_version'):
            msg = ('simple-virtuoso-migrate v%s' %
                                            SIMPLE_VIRTUOSO_MIGRATE_VERSION)
            CLI.info_and_exit(msg)

        if options.get('show_colors'):
            CLI.show_colors()

        # Create config
        if options.get('config_file'):
            config = FileConfig(options.get('config_file'),
                                options.get('environment'))
        else:
            config = Config()

        config.update('schema_version', options.get('schema_version'))
        config.update('show_sparql', options.get('show_sparql'))
        config.update('show_sparql_only', options.get('show_sparql_only'))
        config.update('file_migration', options.get('file_migration'))
        #config.update('add_ttl', options.get('add_ttl'))
        config.update('load_ttl', options.get('load_ttl'))
        config.update('log_dir', options.get('log_dir'))
        config.update('database_user', options.get('database_user'))
        config.update('database_password', options.get('database_password'))
        config.update('host_user', options.get('host_user'))
        config.update('host_password', options.get('host_password'))
        config.update('virtuoso_dirs_allowed',
                      options.get('virtuoso_dirs_allowed'))
        config.update('database_host', options.get('database_host'))
        config.update('database_port', options.get('database_port'))
        config.update('database_endpoint', options.get('database_endpoint'))
        config.update('database_graph', options.get('database_graph'))
        config.update('database_ontology', options.get('database_ontology'))
        if options.get('database_migrations_dir'):
            config.update("database_migrations_dir",
                          Config._parse_migrations_dir(
                                            options.get(
                                                'database_migrations_dir')))

        config.update("database_migrations_dir",
                      config.get("database_migrations_dir")[0])
        config.update('log_level', int(options.get('log_level')))

        # Ask the password for user if configured
        if config.get('database_password') == '<<ask_me>>':
            CLI.msg('\nPlease inform password to connect to virtuoso (DATABASE) "%s@%s"' % (config.get('database_user'),
                                                config.get('database_host')))
            passwd = getpass()
            config.update('database_password', passwd)

        is_local = config.get('database_host', '').lower() in ["localhost",
                                                               "127.0.0.1"]
        if config.get('load_ttl') and\
                config.get('virtuoso_dirs_allowed') is None and\
                not is_local:
            if config.get('host_password') == '<<ask_me>>':
                msg = '\nPlease inform password to connect to virtuoso (HOST) "%s@%s"'
                CLI.msg(msg % (config.get('host_user'),
                               config.get('database_host')))
                passwd = getpass()
                config.update('host_password', passwd)
        # If CLI was correctly parsed, execute db-virtuoso.
        Main(config).execute()
    except KeyboardInterrupt:
        CLI.info_and_exit("\nExecution interrupted by user...")
    except Exception, e:
        CLI.error_and_exit(unicode(e))
Exemple #13
0
def run(options):
    try:
        if options.get('simple_db_migrate_version'):
            msg = 'simple-db-migrate v%s' % SIMPLE_DB_MIGRATE_VERSION
            CLI.info_and_exit(msg)

        if options.get('show_colors'):
            CLI.show_colors()

        # Create config
        if options.get('config_file') or os.path.exists('simple-db-migrate.conf'):
            config = FileConfig(options.get('config_file') or 'simple-db-migrate.conf', options.get('environment'))
        else:
            config = Config()

        config.update('schema_version', options.get('schema_version'))
        config.update('show_sql', options.get('show_sql'))
        config.update('show_sql_only', options.get('show_sql_only'))
        config.update('new_migration', options.get('new_migration'))
        config.update('drop_db_first', options.get('drop_db_first'))
        config.update('paused_mode', options.get('paused_mode'))
        config.update('log_dir', options.get('log_dir'))
        config.update('label_version', options.get('label_version'))
        config.update('force_use_files_on_down', options.get('force_use_files_on_down'))
        config.update('force_execute_old_migrations_versions', options.get('force_execute_old_migrations_versions'))
        config.update('utc_timestamp', options.get('utc_timestamp'))
        config.update('database_user', options.get('database_user'))
        config.update('database_password', options.get('database_password'))
        config.update('database_host', options.get('database_host'))
        config.update('database_port', options.get('database_port'))
        config.update('database_name', options.get('database_name'))

        if config.get('database_port', None):
            config.update('database_port', int(config.get('database_port')))

        if options.get('database_migrations_dir'):
            config.update("database_migrations_dir", Config._parse_migrations_dir(options.get('database_migrations_dir')))

        config.update('database_engine', options.get('database_engine'))
        if not config.get('database_engine', None):
            config.update('database_engine', "mysql")

        config.update('database_version_table', options.get('database_version_table'))
        if not config.get('database_version_table', None):
            config.update('database_version_table', "__db_version__")

        # paused mode forces log_level to 2
        log_level = int(options.get('log_level'))
        if options.get('paused_mode'):
            log_level = 2

        config.update('log_level', log_level)

        # Ask the password for user if configured
        if config.get('database_password') == '<<ask_me>>':
            if options.get('password'):
                passwd = options.get('password')
            else:
                CLI.msg('\nPlease inform password to connect to database "%s@%s:%s"' % (config.get('database_user'), config.get('database_host'), config.get('database_name')))
                passwd = getpass()
            config.update('database_password', passwd)

        if options.get('info_database'):
            if options.get('info_database').lower() == 'last_label':
                CLI.info_and_exit(Main(config).last_label() or "NONE")
            elif options.get('info_database').lower() == 'labels':
                labels = Main(config).labels()
                CLI.info_and_exit(labels and "\n".join(labels) or "NONE")
            else:
                CLI.error_and_exit("The '%s' is a wrong parameter for info" % options.get('info_database').lower())

        # If CLI was correctly parsed, execute db-migrate.
        Main(config).execute()
    except KeyboardInterrupt:
        CLI.info_and_exit("\nExecution interrupted by user...")
    except Exception, e:
        CLI.error_and_exit(str(e))
Exemple #14
0
class Main(object):

    def __init__(self, config=None, mysql=None, db_migrate=None):
        self.cli = CLI()
        self.config = config or {}
        self.log = LOG(self.config.get("log_dir"))

        self.mysql = mysql
        if self.mysql is None and not self.config.get("new_migration"):
            self.mysql = MySQL(config)

        self.db_migrate = db_migrate or SimpleDBMigrate(config)

    def execution_log(self, msg, color="CYAN", log_level_limit=2):
        if self.config.get("log_level") >= log_level_limit:
            self.cli.msg(msg)
        self.log.debug(msg)

    def execute(self):
        self.execution_log("\nStarting DB migration...", "PINK", log_level_limit=1)
        if self.config.get("new_migration"):
            self.create_migration()
        else:
            self.migrate()
        self.execution_log("\nDone.\n", "PINK", log_level_limit=1)

    def create_migration(self):
        migrations_dir = self.config.get("migrations_dir")
        new_file = Migration.create(self.config.get("new_migration"), migrations_dir[0], self.config.get("db_script_encoding", "utf-8"))
        self.execution_log("- Created file '%s'" % (new_file), log_level_limit=1)

    def migrate(self):
        destination_version = self.get_destination_version()
        current_version = self.mysql.get_current_schema_version()

        # do it!
        self.execute_migrations(current_version, destination_version)

    def get_destination_version(self):
        destination_version = self.config.get("schema_version")
        if destination_version is None:
            destination_version = self.db_migrate.latest_version_available()

        if destination_version is not '0' and not self.db_migrate.check_if_version_exists(destination_version):
            raise Exception("version not found (%s)" % destination_version)

        return destination_version

    def get_migration_files_to_be_executed(self, current_version, destination_version, is_migration_up):
        mysql_versions = self.mysql.get_all_schema_versions()
        migration_versions = self.db_migrate.get_all_migration_versions()

        # migration up
        if is_migration_up:
            remaining_versions_to_execute = Lists.subtract(migration_versions, mysql_versions)
            remaining_migrations_to_execute = [self.db_migrate.get_migration_from_version_number(version) for version in remaining_versions_to_execute if version <= destination_version]
            return remaining_migrations_to_execute

        # migration down...
        destination_version_id = self.mysql.get_version_id_from_version_number(destination_version)
        migrations = self.mysql.get_all_schema_migrations()
        down_migrations_to_execute = [migration for migration in migrations if migration.id > destination_version_id]
        for migration in down_migrations_to_execute:
            if not migration.sql_down:
                if migration.version not in migration_versions:
                    raise Exception("impossible to migrate down: one of the versions was not found (%s)" % migration.version)
                migration_tmp = self.db_migrate.get_migration_from_version_number(migration.version)
                migration.sql_up = migration_tmp.sql_up
                migration.sql_down = migration_tmp.sql_down
                migration.file_name = migration_tmp.file_name

        down_migrations_to_execute.reverse()
        return down_migrations_to_execute

    def execute_migrations(self, current_version, destination_version):
        """
        passed a version:
            this version don't exists in the database and is younger than the last version -> do migrations up until the this version
            this version don't exists in the database and is older than the last version -> do nothing, is a unpredictable behavior
            this version exists in the database and is older than the last version -> do migrations down until this version

        didn't pass a version -> do migrations up until the last available version
        """

        is_migration_up = True
        # check if a version was passed to the program
        if self.config.get("schema_version"):
            # if was passed and this version is present in the database, check if is older than the current version
            destination_version_id = self.mysql.get_version_id_from_version_number(destination_version)
            if destination_version_id:
                current_version_id = self.mysql.get_version_id_from_version_number(current_version)
                # if this version is previous to the current version in database, then will be done a migration down to this version
                if current_version_id > destination_version_id:
                    is_migration_up = False
            # if was passed and this version is not present in the database and is older than the current version, raise an exception
            # cause is trying to go down to something that never was done
            elif current_version > destination_version:
                raise Exception("Trying to migrate to a lower version wich is not found on database (%s)" % destination_version)

        # getting only the migration sql files to be executed
        migrations_to_be_executed = self.get_migration_files_to_be_executed(current_version, destination_version, is_migration_up)

        self.execution_log("- Current version is: %s" % current_version, "GREEN", log_level_limit=1)

        if migrations_to_be_executed is None or len(migrations_to_be_executed) == 0:
            self.execution_log("- Destination version is: %s" % current_version, "GREEN", log_level_limit=1)
            self.execution_log("\nNothing to do.\n", "PINK", log_level_limit=1)
            return

        self.execution_log("- Destination version is: %s" % (is_migration_up and migrations_to_be_executed[-1].version or destination_version), "GREEN", log_level_limit=1)

        up_down_label = is_migration_up and "up" or "down"
        if self.config.get("show_sql_only"):
            self.execution_log("\nWARNING: database migrations are not being executed ('--showsqlonly' activated)", "YELLOW", log_level_limit=1)
        else:
            self.execution_log("\nStarting migration %s!" % up_down_label, log_level_limit=1)

        if self.config.get("log_level") >= 1:
            self.execution_log("*** versions: %s\n" % ([ migration.version for migration in migrations_to_be_executed]), "CYAN", log_level_limit=1)

        sql_statements_executed = []
        for migration in migrations_to_be_executed:
            sql = is_migration_up and migration.sql_up or migration.sql_down

            if not self.config.get("show_sql_only"):
                if self.config.get("log_level") >= 1:
                    self.execution_log("===== executing %s (%s) =====" % (migration.file_name, up_down_label), log_level_limit=1)

                self.mysql.change(sql, migration.version, migration.file_name, migration.sql_up, migration.sql_down, is_migration_up, execution_log=self.execution_log)

                # paused mode
                if self.config.get("paused_mode"):
                    raw_input("* press <enter> to continue... ")

            # recording the last statement executed
            sql_statements_executed.append(sql)

        if self.config.get("show_sql") or self.config.get("show_sql_only"):
            self.execution_log("__________ SQL statements executed __________", "YELLOW", log_level_limit=1)
            for sql in sql_statements_executed:
                self.execution_log(sql, "YELLOW", log_level_limit=1)
            self.execution_log("_____________________________________________", "YELLOW", log_level_limit=1)
def run(options):
    try:
        if options.get('simple_db_migrate_version'):
            msg = 'simple-db-migrate v%s' % SIMPLE_DB_MIGRATE_VERSION
            CLI.info_and_exit(msg)

        if options.get('show_colors'):
            CLI.show_colors()

        # Create config
        if options.get('config_file'):
            config = FileConfig(options.get('config_file'), options.get('environment'))
        else:
            config = Config()

        config.update('schema_version', options.get('schema_version'))
        config.update('show_sql', options.get('show_sql'))
        config.update('show_sql_only', options.get('show_sql_only'))
        config.update('new_migration', options.get('new_migration'))
        config.update('drop_db_first', options.get('drop_db_first'))
        config.update('paused_mode', options.get('paused_mode'))
        config.update('log_dir', options.get('log_dir'))
        config.update('label_version', options.get('label_version'))
        config.update('force_use_files_on_down', options.get('force_use_files_on_down'))
        config.update('force_execute_old_migrations_versions', options.get('force_execute_old_migrations_versions'))
        config.update('utc_timestamp', options.get('utc_timestamp'))
        config.update('database_user', options.get('database_user'))
        config.update('database_password', options.get('database_password'))
        config.update('database_host', options.get('database_host'))
        config.update('database_name', options.get('database_name'))
        if options.get('database_migrations_dir'):
            config.update("database_migrations_dir", Config._parse_migrations_dir(options.get('database_migrations_dir')))

        config.update('database_engine', options.get('database_engine'))
        if not config.get('database_engine', None):
            config.update('database_engine', "mysql")

        config.update('database_version_table', options.get('database_version_table'))
        if not config.get('database_version_table', None):
            config.update('database_version_table', "__db_version__")

        # paused mode forces log_level to 2
        log_level = int(options.get('log_level'))
        if options.get('paused_mode'):
            log_level = 2

        config.update('log_level', log_level)

        # Ask the password for user if configured
        if config.get('database_password') == '<<ask_me>>':
            if options.get('password'):
                passwd = options.get('password')
            else:
                CLI.msg('\nPlease inform password to connect to database "%s@%s:%s"' % (config.get('database_user'), config.get('database_host'), config.get('database_name')))
                passwd = getpass()
            config.update('database_password', passwd)

        # If CLI was correctly parsed, execute db-migrate.
        Main(config).execute()
    except KeyboardInterrupt:
        CLI.info_and_exit("\nExecution interrupted by user...")
    except Exception, e:
        CLI.error_and_exit(str(e))
Exemple #16
0
class Main(object):

    def __init__(self, config=None, sgdb=None, db_migrate=None, execution_log=None):
        self.cli = CLI()
        self.config = config or {}
        self.log = LOG(self.config.get("log_dir", None))

        self.sgdb = sgdb
        if self.sgdb is None and not self.config.get("new_migration", None):
            if self.config.get("db_engine") is 'mysql':
                from mysql import MySQL
                self.sgdb = MySQL(config)
            elif self.config.get("db_engine") is 'oracle':
                from oracle import Oracle
                self.sgdb = Oracle(config)

        self.db_migrate = db_migrate or SimpleDBMigrate(config)
        if execution_log:
            self.execution_log = execution_log

    def execution_log(self, msg, color="CYAN", log_level_limit=2):
        if self.config.get("log_level", 1) >= log_level_limit:
            self.cli.msg(msg)
        self.log.debug(msg)

    def execute(self):
        self.execution_log("\nStarting DB migration...", "PINK", log_level_limit=1)
        if self.config.get("new_migration", None):
            self.create_migration()
        else:
            self.migrate()
        self.execution_log("\nDone.\n", "PINK", log_level_limit=1)

    def create_migration(self):
        migrations_dir = self.config.get("migrations_dir")
        new_file = Migration.create(self.config.get("new_migration", None), migrations_dir[0], self.config.get("db_script_encoding", "utf-8"), self.config.get("utc_timestamp", False))
        self.execution_log("- Created file '%s'" % (new_file), log_level_limit=1)

    def migrate(self):
        destination_version = self.get_destination_version()
        current_version = self.sgdb.get_current_schema_version()

        # do it!
        self.execute_migrations(current_version, destination_version)

    def get_destination_version(self):
        label_version = self.config.get("label_version", None)
        schema_version = self.config.get("schema_version", None)

        destination_version = None
        destination_version_by_label = None
        destination_version_by_schema = None

        if label_version is not None:
            destination_version_by_label = self.sgdb.get_version_number_from_label(label_version)
            """
            if specified label exists at database and schema version was not specified,
            is equivalent to run simple-db-migrate with schema_version equals to the version with specified label
            """
            if destination_version_by_label is not None and schema_version is None:
                schema_version = destination_version_by_label
                self.config.remove("schema_version")
                self.config.put("schema_version", destination_version_by_label)


        if schema_version is not None and self.sgdb.get_version_id_from_version_number(schema_version):
            destination_version_by_schema = schema_version

        if label_version is None:
            if schema_version is None:
                destination_version = self.db_migrate.latest_version_available()
            elif destination_version_by_schema is None:
                destination_version = schema_version
            else:
                destination_version = destination_version_by_schema
        else:
            if schema_version is None:
                destination_version = self.db_migrate.latest_version_available()
            elif (destination_version_by_label is None) or (destination_version_by_schema == destination_version_by_label):
                destination_version = schema_version

        if (destination_version_by_schema is not None) and (destination_version_by_label is not None) and (destination_version_by_schema != destination_version_by_label):
            raise Exception("label (%s) and schema_version (%s) don't correspond to the same version at database" % (label_version, schema_version))

        if (schema_version is not None and label_version is not None) and ((destination_version_by_schema is not None and destination_version_by_label is None) or (destination_version_by_schema is None and destination_version_by_label is not None)):
            raise Exception("label (%s) or schema_version (%s), only one of them exists in the database" % (label_version, schema_version))

        if destination_version is not '0' and not (self.db_migrate.check_if_version_exists(destination_version) or self.sgdb.get_version_id_from_version_number(destination_version)):
            raise Exception("version not found (%s)" % destination_version)

        return destination_version

    def get_migration_files_to_be_executed(self, current_version, destination_version, is_migration_up):
        if current_version == destination_version and not self.config.get("force_execute_old_migrations_versions", False):
            return []
        schema_versions = self.sgdb.get_all_schema_versions()
        migration_versions = self.db_migrate.get_all_migration_versions()

        # migration up
        if is_migration_up:
            remaining_versions_to_execute = Lists.subtract(migration_versions, schema_versions)
            remaining_migrations_to_execute = [self.db_migrate.get_migration_from_version_number(version) for version in remaining_versions_to_execute if version <= destination_version]
            return remaining_migrations_to_execute

        # migration down...
        destination_version_id = self.sgdb.get_version_id_from_version_number(destination_version)
        migrations = self.sgdb.get_all_schema_migrations()
        down_migrations_to_execute = [migration for migration in migrations if migration.id > destination_version_id]
        force_files = self.config.get("force_use_files_on_down", False)
        for migration in down_migrations_to_execute:
            if not migration.sql_down or force_files:
                if migration.version not in migration_versions:
                    raise Exception("impossible to migrate down: one of the versions was not found (%s)" % migration.version)
                migration_tmp = self.db_migrate.get_migration_from_version_number(migration.version)
                migration.sql_up = migration_tmp.sql_up
                migration.sql_down = migration_tmp.sql_down
                migration.file_name = migration_tmp.file_name

        down_migrations_to_execute.reverse()
        return down_migrations_to_execute

    def execute_migrations(self, current_version, destination_version):
        """
        passed a version:
            this version don't exists in the database and is younger than the last version -> do migrations up until the this version
            this version don't exists in the database and is older than the last version -> do nothing, is a unpredictable behavior
            this version exists in the database and is older than the last version -> do migrations down until this version

        didn't pass a version -> do migrations up until the last available version
        """

        is_migration_up = True
        # check if a version was passed to the program
        if self.config.get("schema_version"):
            # if was passed and this version is present in the database, check if is older than the current version
            destination_version_id = self.sgdb.get_version_id_from_version_number(destination_version)
            if destination_version_id:
                current_version_id = self.sgdb.get_version_id_from_version_number(current_version)
                # if this version is previous to the current version in database, then will be done a migration down to this version
                if current_version_id > destination_version_id:
                    is_migration_up = False
            # if was passed and this version is not present in the database and is older than the current version, raise an exception
            # cause is trying to go down to something that never was done
            elif current_version > destination_version:
                raise Exception("Trying to migrate to a lower version wich is not found on database (%s)" % destination_version)

        # getting only the migration sql files to be executed
        migrations_to_be_executed = self.get_migration_files_to_be_executed(current_version, destination_version, is_migration_up)

        self.execution_log("- Current version is: %s" % current_version, "GREEN", log_level_limit=1)

        if migrations_to_be_executed is None or len(migrations_to_be_executed) == 0:
            self.execution_log("- Destination version is: %s" % current_version, "GREEN", log_level_limit=1)
            self.execution_log("\nNothing to do.\n", "PINK", log_level_limit=1)
            return

        self.execution_log("- Destination version is: %s" % (is_migration_up and migrations_to_be_executed[-1].version or destination_version), "GREEN", log_level_limit=1)

        up_down_label = is_migration_up and "up" or "down"
        if self.config.get("show_sql_only", False):
            self.execution_log("\nWARNING: database migrations are not being executed ('--showsqlonly' activated)", "YELLOW", log_level_limit=1)
        else:
            self.execution_log("\nStarting migration %s!" % up_down_label, log_level_limit=1)

        self.execution_log("*** versions: %s\n" % ([ migration.version for migration in migrations_to_be_executed]), "CYAN", log_level_limit=1)

        sql_statements_executed = []
        for migration in migrations_to_be_executed:
            sql = is_migration_up and migration.sql_up or migration.sql_down

            if not self.config.get("show_sql_only", False):
                self.execution_log("===== executing %s (%s) =====" % (migration.file_name, up_down_label), log_level_limit=1)

                label = None
                if is_migration_up:
                    label = self.config.get("label_version", None)

                try:
                    self.sgdb.change(sql, migration.version, migration.file_name, migration.sql_up, migration.sql_down, is_migration_up, self.execution_log, label)
                except Exception, e:
                    self.execution_log("===== ERROR executing %s (%s) =====" % (migration.abspath, up_down_label), log_level_limit=1)
                    raise e

                # paused mode
                if self.config.get("paused_mode", False):
                    raw_input("* press <enter> to continue... ")

            # recording the last statement executed
            sql_statements_executed.append(sql)

        if self.config.get("show_sql", False) or self.config.get("show_sql_only", False):
            self.execution_log("__________ SQL statements executed __________", "YELLOW", log_level_limit=1)
            for sql in sql_statements_executed:
                self.execution_log(sql, "YELLOW", log_level_limit=1)
            self.execution_log("_____________________________________________", "YELLOW", log_level_limit=1)
Exemple #17
0
 def _execution_log(self, msg, color="CYAN", log_level_limit=2):
     if self.config.get("log_level", 1) >= log_level_limit:
         CLI.msg(msg, color)
     self.log.debug(msg)
def run(options):
    """ Initial Module. Treat Parameters and call Main Module for execution """
    try:
        if options.get("simple_virtuoso_migrate_version"):
            msg = "simple-virtuoso-migrate v%s" % SIMPLE_VIRTUOSO_MIGRATE_VERSION
            CLI.info_and_exit(msg)

        if options.get("show_colors"):
            CLI.show_colors()

        # Create config
        if options.get("config_file"):
            config = FileConfig(options.get("config_file"), options.get("environment"))
        else:
            config = Config()

        config.update("schema_version", options.get("schema_version"))
        config.update("show_sparql", options.get("show_sparql"))
        config.update("show_sparql_only", options.get("show_sparql_only"))
        config.update("file_migration", options.get("file_migration"))
        # config.update('add_ttl', options.get('add_ttl'))
        config.update("load_ttl", options.get("load_ttl"))
        config.update("log_dir", options.get("log_dir"))
        config.update("database_user", options.get("database_user"))
        config.update("database_password", options.get("database_password"))
        config.update("host_user", options.get("host_user"))
        config.update("host_password", options.get("host_password"))
        config.update("virtuoso_dirs_allowed", options.get("virtuoso_dirs_allowed"))
        config.update("database_host", options.get("database_host"))
        config.update("database_port", options.get("database_port"))
        config.update("database_endpoint", options.get("database_endpoint"))
        config.update("database_graph", options.get("database_graph"))
        config.update("database_ontology", options.get("database_ontology"))
        if options.get("database_migrations_dir"):
            config.update(
                "database_migrations_dir", Config._parse_migrations_dir(options.get("database_migrations_dir"))
            )

        config.update("database_migrations_dir", config.get("database_migrations_dir")[0])
        config.update("log_level", int(options.get("log_level")))

        # Ask the password for user if configured
        if config.get("database_password") == "<<ask_me>>":
            CLI.msg(
                '\nPlease inform password to connect to\
                virtuoso (DATABASE) "%s@%s"'
                % (config.get("database_user"), config.get("database_host"))
            )
            passwd = getpass()
            config.update("database_password", passwd)

        is_local = config.get("database_host", "").lower() in ["localhost", "127.0.0.1"]
        # import pdb; pdb.set_trace()
        if config.get("load_ttl") and config.get("virtuoso_dirs_allowed") is None and not is_local:
            if config.get("host_password") == "<<ask_me>>":
                CLI.msg(
                    '\nPlease inform password to connect to\
                virtuoso (HOST) "%s@%s"'
                    % (config.get("host_user"), config.get("database_host"))
                )
                passwd = getpass()
                config.update("host_password", passwd)
        # If CLI was correctly parsed, execute db-virtuoso.
        Main(config).execute()
    except KeyboardInterrupt:
        CLI.info_and_exit("\nExecution interrupted by user...")
    except Exception, e:
        CLI.error_and_exit(unicode(e))