diff --git a/createdb.py b/createdb.py index 6d97d47a..8b65d919 100755 --- a/createdb.py +++ b/createdb.py @@ -5,4 +5,4 @@ import rida.database config = rida.config.from_file("rida.conf") -rida.database.Database.create_tables(config.db, True) +rida.database.Database.create_tables(config, True) diff --git a/rida.py b/rida.py index 51178c81..8b067fd5 100755 --- a/rida.py +++ b/rida.py @@ -97,10 +97,10 @@ def submit_build(): mmd.loads(yaml) except: return "Invalid modulemd", 422 - if db.session.query(rida.database.Module).filter_by(name=mmd.name, + if db.session.query(rida.database.ModuleBuild).filter_by(name=mmd.name, version=mmd.version, release=mmd.release).first(): return "Module already exists", 409 - module = rida.database.Module(name=mmd.name, version=mmd.version, + module = rida.database.ModuleBuild(name=mmd.name, version=mmd.version, release=mmd.release, state="init", modulemd=yaml) db.session.add(module) db.session.commit() @@ -120,7 +120,7 @@ def submit_build(): return "Failed to get the latest commit: %s" % pkgname, 422 if not rida.scm.SCM(pkg["repository"] + "?#" + pkg["commit"]).is_available(): return "Cannot checkout %s" % pkgname, 422 - build = rida.database.Build(module_id=module.id, package=pkgname, format="rpms") + build = rida.database.ComponentBuild(module_id=module.id, package=pkgname, format="rpms") db.session.add(build) module.modulemd = mmd.dumps() module.state = rida.database.BUILD_STATES["init"] @@ -143,17 +143,17 @@ def submit_build(): def query_builds(): """Lists all tracked module builds.""" return json.dumps([{"id": x.id, "state": x.state} - for x in db.session.query(rida.database.Module).all()]), 200 + for x in db.session.query(rida.database.ModuleBuild).all()]), 200 @app.route("/rida/module-builds/", methods=["GET"]) def query_build(id): """Lists details for the specified module builds.""" - module = db.session.query(rida.database.Module).filter_by(id=id).first() + module = db.session.query(rida.database.ModuleBuild).filter_by(id=id).first() if module: tasks = dict() if module.state != "init": - for build in db.session.query(rida.database.Build).filter_by(module_id=id).all(): + for build in db.session.query(rida.database.ComponentBuild).filter_by(module_id=id).all(): tasks[build.format + "/" + build.package] = \ str(build.task) + "/" + build.state return json.dumps({ diff --git a/rida/__init__.py b/rida/__init__.py index e6b6df0d..dc2fc0a8 100644 --- a/rida/__init__.py +++ b/rida/__init__.py @@ -41,3 +41,4 @@ for a number of tasks: infrastructure services can pick up the work. """ +from rida.database import BUILD_STATES diff --git a/rida/database.py b/rida/database.py index 6b602a5f..cdceaa34 100644 --- a/rida/database.py +++ b/rida/database.py @@ -83,31 +83,36 @@ class Database(object): return self._session @classmethod - def create_tables(cls, db_url, debug=False): + def create_tables(cls, config, debug=False): """ Creates our tables in the database. - :arg db_url, URL used to connect to the database. The URL contains - information with regards to the database engine, the host to connect - to, the user and password and the database name. + :arg config, config object with a 'db' URL attached to it. ie: ://:@/ :kwarg debug, a boolean specifying wether we should have the verbose output of sqlalchemy or not. :return a Database connection that can be used to query to db. """ - engine = create_engine(db_url, echo=debug) + engine = create_engine(config.db, echo=debug) Base.metadata.create_all(engine) - return cls(db_url, debug=debug) + return cls(config, debug=debug) class Module(Base): __tablename__ = "modules" + name = Column(String, primary_key=True) + + +class ModuleBuild(Base): + __tablename__ = "module_builds" id = Column(Integer, primary_key=True) - name = Column(String, nullable=False) + name = Column(String, ForeignKey('modules.name'), nullable=False) version = Column(String, nullable=False) release = Column(String, nullable=False) state = Column(Integer, nullable=False) modulemd = Column(String, nullable=False) + module = relationship('Module', backref='module_builds', lazy=False) + @validates('state') def validate_state(self, key, field): if field in BUILD_STATES.values(): @@ -128,12 +133,12 @@ class Module(Base): #'modulemd': self.modulemd, # TODO, show their entire .json() ? - 'builds': [build.id for build in self.builds], + 'component_builds': [build.id for build in self.component_builds], } -class Build(Base): - __tablename__ = "builds" +class ComponentBuild(Base): + __tablename__ = "component_builds" id = Column(Integer, primary_key=True) package = Column(String, nullable=False) # XXX: Consider making this a proper ENUM @@ -142,8 +147,8 @@ class Build(Base): # XXX: Consider making this a proper ENUM (or an int) state = Column(String) - module_id = Column(Integer, ForeignKey('modules.id'), nullable=False) - module = relationship('Module', backref='builds', lazy=False) + module_id = Column(Integer, ForeignKey('module_builds.id'), nullable=False) + module_build = relationship('ModuleBuild', backref='component_builds', lazy=False) def json(self): return { @@ -152,5 +157,5 @@ class Build(Base): 'format': self.format, 'task': self.task, 'state': self.state, - 'module': self.module.id, + 'module_build': self.module_build.id, } diff --git a/rida/scheduler/main.py b/rida/scheduler/main.py index 57c4bc52..bc7cf87c 100644 --- a/rida/scheduler/main.py +++ b/rida/scheduler/main.py @@ -37,6 +37,8 @@ import threading import rida.config import rida.messaging +import rida.scheduler.handlers.modules +#import rida.scheduler.handlers.builds import koji @@ -51,12 +53,16 @@ config = rida.config.from_file("rida.conf") # TODO: Set the build state to failed if the module build fails. class Messaging(threading.Thread): + + # These are our main lookup tables for figuring out what to run in response + # to what messaging events. on_build_change = { koji.BUILD_STATES["BUILDING"]: lambda x: x } on_module_change = { rida.BUILD_STATES["new"]: rida.scheduler.handlers.modules.new, } + def sanity_check(self): """ On startup, make sure our implementation is sane. """ # Ensure we have every state covered