Merge #3 Basics of messaging.

This commit is contained in:
Petr Šabata
2016-06-30 16:39:20 +00:00
5 changed files with 96 additions and 38 deletions

11
fedmsg.d/rida.py Normal file
View File

@@ -0,0 +1,11 @@
import socket
hostname = socket.gethostname().split('.')[0]
config = {
# Just enough fedmsg config to start publishing...
"endpoints": {
"rida.%s" % hostname: [
"tcp://127.0.0.1:300%i" % i for i in range(10)
],
},
}

16
rida.py
View File

@@ -36,7 +36,7 @@ This is the implementation of the orchestrator's public RESTful API.
# TODO: Emit messages about module submission.
from flask import Flask, request
from rida import config, database
from rida import config, database, messaging
import json
import modulemd
@@ -86,8 +86,19 @@ def submit_build():
module.state = "wait"
db.session.add(module)
db.session.commit()
# Publish to whatever bus we're configured to connect to.
# This should notify ridad to start doing the work we just scheduled.
messaging.publish(
modname='rida',
topic='module.state.change',
msg=module.json(),
backend=conf.messaging,
)
# XXX: Okay, we're pretending here...
return json.dumps({"id": module.id}), 201
return json.dumps(module.json()), 201
@app.route("/rida/module-builds/", methods=["GET"])
def query_builds():
@@ -95,6 +106,7 @@ def query_builds():
return json.dumps([{"id": x.id, "state": x.state}
for x in db.session.query(database.Module).all()]), 200
@app.route("/rida/module-builds/<int:id>", methods=["GET"])
def query_build(id):
"""Lists details for the specified module builds."""

View File

@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -22,14 +20,23 @@
# SOFTWARE.
#
# Written by Petr Šabata <contyk@redhat.com>
# Ralph Bean <rbean@redhat.com>
"""Database handler functions."""
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, String, ForeignKey, create_engine
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class RidaBase(object):
# TODO -- we can implement functionality here common to all our model
# classes.
pass
Base = declarative_base(cls=RidaBase)
class Database(object):
"""Class for handling database connections."""
@@ -50,21 +57,48 @@ class Database(object):
class Module(Base):
__tablename__ = "modules"
id = Column(Integer, primary_key=True)
name = Column(String)
version = Column(String)
release = Column(String)
name = Column(String, nullable=False)
version = Column(String, nullable=False)
release = Column(String, nullable=False)
# XXX: Consider making this a proper ENUM
state = Column(String)
modulemd = Column(String)
state = Column(String, nullable=False)
modulemd = Column(String, nullable=False)
def json(self):
return {
'id': self.id,
'name': self.name,
'version': self.version,
'release': self.release,
'state': self.state,
# This is too spammy..
#'modulemd': self.modulemd,
# TODO, show their entire .json() ?
'builds': [build.id for build in self.builds],
}
class Build(Base):
__tablename__ = "builds"
id = Column(Integer, primary_key=True)
# XXX: Consider making this a proper foreign key
module_id = Column(Integer)
package = Column(String)
package = Column(String, nullable=False)
# XXX: Consider making this a proper ENUM
format = Column(String)
format = Column(String, nullable=False)
task = Column(Integer)
# XXX: Consider making this a proper ENUM
# 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)
def json(self):
return {
'id': self.id,
'package': self.package,
'format': self.format,
'task': self.task,
'state': self.state,
'module': self.module.id,
}

View File

@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2016 Red Hat, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -21,6 +19,27 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Written by Petr Šabata <contyk@redhat.com>
# Written by Ralph Bean <rbean@redhat.com>
"""Generic messaging functions."""
def publish(topic, msg, backend, modname='rida'):
try:
handler = _messaging_backends[backend]['publish']
except KeyError:
raise KeyError("No messaging backend found for %r" % backend)
return handler(topic, msg, modname=modname)
def _fedmsg_publish(topic, msg, modname):
import fedmsg
return fedmsg.publish(topic=topic, msg=msg, modname=modname)
_messaging_backends = {
'fedmsg': {
'publish': _fedmsg_publish,
#'listen': _fedmsg_listen, # For later...
},
}

View File

@@ -1,18 +0,0 @@
CREATE TABLE IF NOT EXISTS modules (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL, -- e.g. foo, module name
version TEXT NOT NULL, -- e.g. 1.23, module version
release TEXT NOT NULL, -- e.g. 4, module release
state TEXT NOT NULL, -- init, wait, build, done, failed, ready
modulemd TEXT NOT NULL -- the entire modulemd file
);
CREATE TABLE IF NOT EXISTS builds (
id INTEGER PRIMARY KEY,
module_id INTEGER NOT NULL,
package TEXT NOT NULL, -- e.g. bar, SRPM name
format TEXT NOT NULL, -- rpm
task INTEGER NOT NULL, -- koji task id
state TEXT NOT NULL, -- koji build states - open, closed, failed
FOREIGN KEY(module_id) REFERENCES modules(id)
);