def __init__(self, dsn=None, schema_check=True, echo=False): """ @param dsn: database connection string. @param schema_check: disable or enable the db schema version check. @param echo: echo sql queries. """ self._lock = SuperLock() cfg = Config() if dsn: self._connect_database(dsn) elif hasattr(cfg, "database") and cfg.database.connection: self._connect_database(cfg.database.connection) else: db_file = os.path.join(CUCKOO_ROOT, "db", "cuckoo.db") if not os.path.exists(db_file): db_dir = os.path.dirname(db_file) if not os.path.exists(db_dir): try: create_folder(folder=db_dir) except CuckooOperationalError as e: raise CuckooDatabaseError( "Unable to create database directory: {0}".format( e)) self._connect_database("sqlite:///%s" % db_file) # Disable SQL logging. Turn it on for debugging. self.engine.echo = echo # Connection timeout. if hasattr(cfg, "database") and cfg.database.timeout: self.engine.pool_timeout = cfg.database.timeout else: self.engine.pool_timeout = 60 # Let's emit a warning just in case. if not hasattr(cfg, "database"): log.warning("It appears you don't have a valid `database` " "section in conf/cuckoo.conf, using sqlite3 instead.") # Create schema. try: Base.metadata.create_all(self.engine) except SQLAlchemyError as e: raise CuckooDatabaseError( "Unable to create or connect to database: {0}".format(e)) # Get db session. self.Session = sessionmaker(bind=self.engine) # Deal with schema versioning. # TODO: it's a little bit dirty, needs refactoring. tmp_session = self.Session() if not tmp_session.query(AlembicVersion).count(): # Set database schema version. tmp_session.add(AlembicVersion(version_num=SCHEMA_VERSION)) try: tmp_session.commit() except SQLAlchemyError as e: raise CuckooDatabaseError( "Unable to set schema version: {0}".format(e)) tmp_session.rollback() finally: tmp_session.close() else: # Check if db version is the expected one. last = tmp_session.query(AlembicVersion).first() tmp_session.close() if last.version_num != SCHEMA_VERSION and schema_check: raise CuckooDatabaseError( "DB schema version mismatch: found {0}, expected {1}. " "Try to apply all migrations (cd utils/db_migration/ && " "alembic upgrade head).".format(last.version_num, SCHEMA_VERSION))
def __init__(self, dsn=None, schema_check=True): """@param dsn: database connection string. @param schema_check: disable or enable the db schema version check """ self._lock = SuperLock() self.cfg = Config() if dsn: self._connect_database(dsn) elif self.cfg.database.connection: self._connect_database(self.cfg.database.connection) else: db_file = os.path.join(CUCKOO_ROOT, "db", "cuckoo.db") if not os.path.exists(db_file): db_dir = os.path.dirname(db_file) if not os.path.exists(db_dir): try: create_folder(folder=db_dir) except CuckooOperationalError as e: raise CuckooDatabaseError( "Unable to create database directory: {0}".format( e)) self._connect_database("sqlite:///%s" % db_file) # Disable SQL logging. Turn it on for debugging. self.engine.echo = False # Connection timeout. if self.cfg.database.timeout: self.engine.pool_timeout = self.cfg.database.timeout else: self.engine.pool_timeout = 60 # Create schema. try: Base.metadata.create_all(self.engine) except SQLAlchemyError as e: raise CuckooDatabaseError( "Unable to create or connect to database: {0}".format(e)) # Get db session. self.Session = sessionmaker(bind=self.engine) @event.listens_for(self.Session, 'after_flush') def delete_tag_orphans(session, ctx): session.query(Tag).filter(~Tag.tasks.any()).filter( ~Tag.machines.any()).delete(synchronize_session=False) # Deal with schema versioning. # TODO: it's a little bit dirty, needs refactoring. tmp_session = self.Session() if not tmp_session.query(AlembicVersion).count(): # Set database schema version. tmp_session.add(AlembicVersion(version_num=SCHEMA_VERSION)) try: tmp_session.commit() except SQLAlchemyError as e: tmp_session.rollback() raise CuckooDatabaseError( "Unable to set schema version: {0}".format(e)) finally: tmp_session.close() else: # Check if db version is the expected one. last = tmp_session.query(AlembicVersion).first() tmp_session.close() if last.version_num != SCHEMA_VERSION and schema_check: raise CuckooDatabaseError( "DB schema version mismatch: found {0}, expected {1}. " "Try to apply all migrations (cd utils/db_migration/ && " "alembic upgrade head).".format(last.version_num, SCHEMA_VERSION))