| |
@@ -110,22 +110,23 @@
|
| |
username = db.Column(db.String(200), nullable=False, unique=True)
|
| |
|
| |
@classmethod
|
| |
- def find_user_by_name(cls, username):
|
| |
+ def find_user_by_name(cls, db_session, username):
|
| |
"""Find a user by username
|
| |
|
| |
:param str username: a string of username to find user
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
:return: user object if found, otherwise None is returned.
|
| |
:rtype: User
|
| |
"""
|
| |
try:
|
| |
- return db.session.query(cls).filter(cls.username == username)[0]
|
| |
+ return db_session.query(cls).filter(cls.username == username)[0]
|
| |
except IndexError:
|
| |
return None
|
| |
|
| |
@classmethod
|
| |
- def create_user(cls, username):
|
| |
+ def create_user(cls, db_session, username):
|
| |
user = cls(username=username)
|
| |
- db.session.add(user)
|
| |
+ db_session.add(user)
|
| |
return user
|
| |
|
| |
|
| |
@@ -171,7 +172,7 @@
|
| |
doc='Whether this event is triggered manually')
|
| |
|
| |
@classmethod
|
| |
- def create(cls, session, message_id, search_key, event_type, released=True,
|
| |
+ def create(cls, db_session, message_id, search_key, event_type, released=True,
|
| |
state=None, manual=False, dry_run=False, requester=None):
|
| |
if event_type in EVENT_TYPES:
|
| |
event_type = EVENT_TYPES[event_type]
|
| |
@@ -187,7 +188,7 @@
|
| |
dry_run=dry_run,
|
| |
requester=requester,
|
| |
)
|
| |
- session.add(event)
|
| |
+ db_session.add(event)
|
| |
return event
|
| |
|
| |
@validates('state')
|
| |
@@ -201,35 +202,35 @@
|
| |
raise ValueError("%s: %s, not in %r" % (key, field, list(EventState)))
|
| |
|
| |
@classmethod
|
| |
- def get(cls, session, message_id):
|
| |
- return session.query(cls).filter_by(message_id=message_id).first()
|
| |
+ def get(cls, db_session, message_id):
|
| |
+ return db_session.query(cls).filter_by(message_id=message_id).first()
|
| |
|
| |
@classmethod
|
| |
- def get_or_create(cls, session, message_id, search_key, event_type,
|
| |
+ def get_or_create(cls, db_session, message_id, search_key, event_type,
|
| |
released=True, manual=False, dry_run=False):
|
| |
- instance = cls.get(session, message_id)
|
| |
+ instance = cls.get(db_session, message_id)
|
| |
if instance:
|
| |
return instance
|
| |
instance = cls.create(
|
| |
- session, message_id, search_key, event_type,
|
| |
+ db_session, message_id, search_key, event_type,
|
| |
released=released, manual=manual, dry_run=dry_run)
|
| |
- session.commit()
|
| |
+ db_session.commit()
|
| |
return instance
|
| |
|
| |
@classmethod
|
| |
- def get_or_create_from_event(cls, session, event, released=True):
|
| |
- return cls.get_or_create(session, event.msg_id,
|
| |
+ def get_or_create_from_event(cls, db_session, event, released=True):
|
| |
+ return cls.get_or_create(db_session, event.msg_id,
|
| |
event.search_key, event.__class__,
|
| |
released=released, manual=event.manual,
|
| |
dry_run=event.dry_run)
|
| |
|
| |
@classmethod
|
| |
- def get_unreleased(cls, session, states=None):
|
| |
+ def get_unreleased(cls, db_session, states=None):
|
| |
"""
|
| |
Returns list of all unreleased events in given states. If no states
|
| |
are provided, returns only events in INITIALIZED, BUILDING or COMPLETE
|
| |
state.
|
| |
- :param session: db.session
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
:param list states: List of states to filter events for. If None,
|
| |
INITIALIZED, BUILDING and COMPLETE is used.
|
| |
:rtype: list of models.Event.
|
| |
@@ -244,15 +245,15 @@
|
| |
state.value if isinstance(state, EventState) else state for
|
| |
state in states
|
| |
]
|
| |
- return session.query(cls).filter(cls.released == false(),
|
| |
- cls.state.in_(states)).all()
|
| |
+ return db_session.query(cls).filter(cls.released == false(),
|
| |
+ cls.state.in_(states)).all()
|
| |
|
| |
@classmethod
|
| |
- def get_by_event_id(cls, session, event_id):
|
| |
- return session.query(cls).filter_by(id=event_id).first()
|
| |
+ def get_by_event_id(cls, db_session, event_id):
|
| |
+ return db_session.query(cls).filter_by(id=event_id).first()
|
| |
|
| |
- def get_image_builds_in_first_batch(self, session):
|
| |
- return session.query(ArtifactBuild).filter_by(
|
| |
+ def get_image_builds_in_first_batch(self, db_session):
|
| |
+ return db_session.query(ArtifactBuild).filter_by(
|
| |
dep_on=None,
|
| |
type=ArtifactType.IMAGE.value,
|
| |
event_id=self.id,
|
| |
@@ -262,58 +263,58 @@
|
| |
def event_type(self):
|
| |
return INVERSE_EVENT_TYPES[self.event_type_id]
|
| |
|
| |
- def add_event_dependency(self, session, event):
|
| |
+ def add_event_dependency(self, db_session, event):
|
| |
"""Add a dependent event
|
| |
|
| |
- :param session: the `db.session`.
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
:param event: the dependent event to be added.
|
| |
:type event: :py:class:`Event`
|
| |
:return: instance of :py:class:`EventDependency`. Caller is responsible
|
| |
for committing changes to database. If `event` has been added
|
| |
already, nothing changed and `None` will be returned.
|
| |
"""
|
| |
- dep = session.query(EventDependency.id).filter_by(
|
| |
+ dep = db_session.query(EventDependency.id).filter_by(
|
| |
event_id=self.id, event_dependency_id=event.id).first()
|
| |
if dep is None:
|
| |
dep = EventDependency(event_id=self.id,
|
| |
event_dependency_id=event.id)
|
| |
- session.add(dep)
|
| |
+ db_session.add(dep)
|
| |
return dep
|
| |
else:
|
| |
return None
|
| |
|
| |
- @property
|
| |
- def event_dependencies(self):
|
| |
+ def get_event_dependencies(self, db_session):
|
| |
"""
|
| |
Returns the list of Events this Event depends on.
|
| |
"""
|
| |
events = []
|
| |
- deps = EventDependency.query.filter_by(event_id=self.id).all()
|
| |
+ deps = db_session.query(EventDependency).filter_by(event_id=self.id).all()
|
| |
for dep in deps:
|
| |
- events.append(Event.query.filter_by(
|
| |
+ events.append(db_session.query(Event).filter_by(
|
| |
id=dep.event_dependency_id).first())
|
| |
return events
|
| |
|
| |
- @property
|
| |
- def depending_events(self):
|
| |
+ def get_depending_events(self, db_session):
|
| |
"""
|
| |
Returns the list of Events depending on this Event.
|
| |
"""
|
| |
depending_events = []
|
| |
- parents = EventDependency.query.filter_by(event_dependency_id=self.id).all()
|
| |
+ parents = db_session.query(EventDependency).filter_by(event_dependency_id=self.id).all()
|
| |
for p in parents:
|
| |
- depending_events.append(Event.query.filter_by(
|
| |
+ depending_events.append(db_session.query(Event).filter_by(
|
| |
id=p.event_id).first())
|
| |
return depending_events
|
| |
|
| |
- def has_all_builds_in_state(self, state):
|
| |
+ def has_all_builds_in_state(self, db_session, state):
|
| |
"""
|
| |
Returns True when all builds are in the given `state`.
|
| |
+
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
"""
|
| |
- return db.session.query(ArtifactBuild).filter_by(
|
| |
+ return db_session.query(ArtifactBuild).filter_by(
|
| |
event_id=self.id).filter(state != state).count() == 0
|
| |
|
| |
- def builds_transition(self, state, reason, filters=None):
|
| |
+ def builds_transition(self, db_session, state, reason, filters=None):
|
| |
"""
|
| |
Calls transition(state, reason) for all builds associated with this
|
| |
event.
|
| |
@@ -328,13 +329,16 @@
|
| |
builds_to_transition = self.builds.filter_by(
|
| |
**filters).all() if isinstance(filters, dict) else self.builds
|
| |
|
| |
- return [build.id
|
| |
- for build in builds_to_transition if build.transition(state, reason)]
|
| |
+ return [
|
| |
+ build.id for build in builds_to_transition
|
| |
+ if build.transition(db_session, state, reason)
|
| |
+ ]
|
| |
|
| |
- def transition(self, state, state_reason=None):
|
| |
+ def transition(self, db_session, state, state_reason=None):
|
| |
"""
|
| |
Sets the time_done, state, and state_reason of this Event.
|
| |
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
:param state: EventState value
|
| |
:param state_reason: Reason why this state has been set.
|
| |
:return: True/False, whether state was changed
|
| |
@@ -368,8 +372,9 @@
|
| |
if EventState(state).counter:
|
| |
EventState(state).counter.inc()
|
| |
|
| |
- db.session.commit()
|
| |
- messaging.publish('event.state.changed', self.json())
|
| |
+ db_session.add(self)
|
| |
+ db_session.commit()
|
| |
+ messaging.publish('event.state.changed', self.json(db_session))
|
| |
messaging.publish('event.state.changed.min', self.json_min())
|
| |
|
| |
return True
|
| |
@@ -390,11 +395,11 @@
|
| |
return {}
|
| |
return json.loads(self.requester_metadata)
|
| |
|
| |
- def json(self):
|
| |
+ def json(self, db_session):
|
| |
data = self._common_json()
|
| |
data['builds'] = [b.json() for b in self.builds]
|
| |
- data['depends_on_events'] = [event.id for event in self.event_dependencies]
|
| |
- data['depending_events'] = [event.id for event in self.depending_events]
|
| |
+ data['depends_on_events'] = [event.id for event in self.get_event_dependencies(db_session)]
|
| |
+ data['depending_events'] = [event.id for event in self.get_depending_events(db_session)]
|
| |
return data
|
| |
|
| |
def json_min(self):
|
| |
@@ -410,7 +415,6 @@
|
| |
|
| |
def _common_json(self):
|
| |
event_url = get_url_for('event', id=self.id)
|
| |
- db.session.add(self)
|
| |
return {
|
| |
"id": self.id,
|
| |
"message_id": self.message_id,
|
| |
@@ -429,7 +433,7 @@
|
| |
"requester_metadata": self.requester_metadata_json,
|
| |
}
|
| |
|
| |
- def find_dependent_events(self):
|
| |
+ def find_dependent_events(self, db_session):
|
| |
"""
|
| |
Find other unreleased Events which built the same builds (or just some
|
| |
of them) as this Event and adds them as a dependency for this event.
|
| |
@@ -437,6 +441,8 @@
|
| |
Dependent events of may also rebuild some same images that current event
|
| |
will build. So, for building images found from current event, we also
|
| |
need those YUM repositories used to build images in dependent events.
|
| |
+
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
"""
|
| |
builds_nvrs = [build.name for build in self.builds]
|
| |
|
| |
@@ -444,7 +450,7 @@
|
| |
EventState.BUILDING.value,
|
| |
EventState.COMPLETE.value]
|
| |
|
| |
- query = db.session.query(ArtifactBuild.event_id)
|
| |
+ query = db_session.query(ArtifactBuild.event_id)
|
| |
dep_event_ids = query.join(ArtifactBuild.event).filter(
|
| |
ArtifactBuild.name.in_(builds_nvrs),
|
| |
ArtifactBuild.event_id != self.id,
|
| |
@@ -455,23 +461,25 @@
|
| |
).distinct()
|
| |
|
| |
dep_events = []
|
| |
- query = db.session.query(Event)
|
| |
+ query = db_session.query(Event)
|
| |
for row in dep_event_ids:
|
| |
dep_event = query.filter_by(id=row[0]).first()
|
| |
- self.add_event_dependency(db.session, dep_event)
|
| |
+ self.add_event_dependency(db_session, dep_event)
|
| |
dep_events.append(dep_event)
|
| |
- db.session.commit()
|
| |
+ db_session.commit()
|
| |
return dep_events
|
| |
|
| |
- def get_artifact_build_from_event_dependencies(self, nvr):
|
| |
+ def get_artifact_build_from_event_dependencies(self, db_session, nvr):
|
| |
"""
|
| |
It returns the artifact build, with `DONE` state, from the event dependencies (the build
|
| |
of the parent event). `nvr` is used as `original_nvr` when finding the `ArtifactBuild`.
|
| |
It returns all the parent artifact builds from the first found event dependency.
|
| |
If the build is not found, it returns None.
|
| |
+
|
| |
+ :param db_session: SQLAlchemy database session object.
|
| |
"""
|
| |
- for parent_event in self.event_dependencies:
|
| |
- parent_build = db.session.query(
|
| |
+ for parent_event in self.get_event_dependencies(db_session):
|
| |
+ parent_build = db_session.query(
|
| |
ArtifactBuild).filter_by(event_id=parent_event.id,
|
| |
original_nvr=nvr,
|
| |
state=ArtifactBuildState.DONE.value).all()
|
| |
@@ -533,7 +541,7 @@
|
| |
composes = db.relationship('ArtifactBuildCompose', back_populates='build')
|
| |
|
| |
@classmethod
|
| |
- def create(cls, session, event, name, type,
|
| |
+ def create(cls, db_session, event, name, type,
|
| |
build_id=None, dep_on=None, state=None,
|
| |
original_nvr=None, rebuilt_nvr=None,
|
| |
rebuild_reason=0):
|
| |
@@ -551,7 +559,7 @@
|
| |
dep_on=dep_on,
|
| |
rebuild_reason=rebuild_reason
|
| |
)
|
| |
- session.add(build)
|
| |
+ db_session.add(build)
|
| |
return build
|
| |
|
| |
@validates('state')
|
| |
@@ -575,12 +583,12 @@
|
| |
raise ValueError("%s: %s, not in %r" % (key, field, list(ArtifactType)))
|
| |
|
| |
@classmethod
|
| |
- def get_lowest_build_id(cls, session):
|
| |
+ def get_lowest_build_id(cls, db_session):
|
| |
"""
|
| |
Returns the lowest build_id. If there is no build so far,
|
| |
returns 0.
|
| |
"""
|
| |
- build = (session.query(ArtifactBuild)
|
| |
+ build = (db_session.query(ArtifactBuild)
|
| |
.filter(cls.build_id != None) # noqa
|
| |
.order_by(ArtifactBuild.build_id.asc())
|
| |
.first())
|
| |
@@ -588,13 +596,13 @@
|
| |
return 0
|
| |
return build.build_id
|
| |
|
| |
- def depending_artifact_builds(self):
|
| |
+ def depending_artifact_builds(self, db_session):
|
| |
"""
|
| |
Returns list of artifact builds depending on this one.
|
| |
"""
|
| |
- return ArtifactBuild.query.filter_by(dep_on_id=self.id).all()
|
| |
+ return db_session.query(ArtifactBuild).filter_by(dep_on_id=self.id).all()
|
| |
|
| |
- def transition(self, state, state_reason):
|
| |
+ def transition(self, db_session, state, state_reason):
|
| |
"""
|
| |
Sets the state and state_reason of this ArtifactBuild.
|
| |
|
| |
@@ -631,11 +639,14 @@
|
| |
# can rebuild them.
|
| |
if self.state in [ArtifactBuildState.FAILED.value,
|
| |
ArtifactBuildState.CANCELED.value]:
|
| |
- for build in self.depending_artifact_builds():
|
| |
+ for build in self.depending_artifact_builds(db_session):
|
| |
build.transition(
|
| |
+ db_session,
|
| |
self.state, "Cannot build artifact, because its "
|
| |
"dependency cannot be built.")
|
| |
|
| |
+ db_session.add(self)
|
| |
+ db_session.commit()
|
| |
messaging.publish('build.state.changed', self.json())
|
| |
|
| |
return True
|
| |
@@ -651,7 +662,6 @@
|
| |
build_args = json.loads(self.build_args)
|
| |
|
| |
build_url = get_url_for('build', id=self.id)
|
| |
- db.session.add(self)
|
| |
return {
|
| |
"id": self.id,
|
| |
"name": self.name,
|
| |
@@ -684,10 +694,10 @@
|
| |
break
|
| |
return dep_on
|
| |
|
| |
- def add_composes(self, session, composes):
|
| |
+ def add_composes(self, db_session, composes):
|
| |
"""Add an ODCS compose to this build"""
|
| |
for compose in composes:
|
| |
- session.add(ArtifactBuildCompose(
|
| |
+ db_session.add(ArtifactBuildCompose(
|
| |
build_id=self.id, compose_id=compose.id))
|
| |
|
| |
@property
|
| |
@@ -712,12 +722,12 @@
|
| |
self.odcs_compose_id)['state_name']
|
| |
|
| |
@classmethod
|
| |
- def get_lowest_compose_id(cls, session):
|
| |
+ def get_lowest_compose_id(cls, db_session):
|
| |
"""
|
| |
Returns the lowest odcs_compose_id. If there is no compose,
|
| |
returns 0.
|
| |
"""
|
| |
- compose = session.query(Compose).order_by(
|
| |
+ compose = db_session.query(Compose).order_by(
|
| |
Compose.odcs_compose_id.asc()).first()
|
| |
if not compose:
|
| |
return 0
|
| |
in memory sqlite db doesn't work after this change.