示例#1
0
class ReplicaCatalog(CatalogMixin, db.Model):
    __tablename__ = 'replica_catalog'
    __table_args__ = (db.UniqueConstraint('user_id', 'name'), {
        'mysql_engine': 'InnoDB'
    })
    __catalog_type__ = 'replica'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    format = db.Column(db.Enum(*RC_FORMATS), nullable=False)
    created = db.Column(db.DateTime, nullable=False)
    updated = db.Column(db.DateTime, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    user = db.relationship("User")

    def __init__(self, user_id, name, format):
        self.user_id = user_id
        self.set_name(name)
        self.set_format(format)
        self.set_created()
        self.set_updated()
示例#2
0
class Ensemble(db.Model, EnsembleMixin):
    __tablename__ = 'ensemble'
    __table_args__ = (
        db.UniqueConstraint('user_id', 'name'),
        {'mysql_engine': 'InnoDB'}
    )

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    created = db.Column(db.DateTime, nullable=False)
    updated = db.Column(db.DateTime, nullable=False)
    state = db.Column(db.Enum(*EnsembleStates), nullable=False)
    max_running = db.Column(db.Integer, nullable=False)
    max_planning = db.Column(db.Integer, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    user = db.relationship("User")

    def __init__(self, user_id, name):
        self.user_id = user_id
        self.set_name(name)
        self.set_created()
        self.set_updated()
        self.state = EnsembleStates.ACTIVE
        self.set_max_running(1)
        self.set_max_planning(1)

    def set_state(self, state):
        state = state.upper()
        if state not in EnsembleStates:
            raise APIError("Invalid ensemble state: %s" % state)
        self.state = state

    def set_max_running(self, max_running):
        try:
            x = int(max_running)
            if max_running < 1:
                raise APIError("Value for max_running must be >= 1: %s" % max_running)
            self.max_running = x
        except ValueError:
            raise APIError("Invalid value for max_running: %s" % max_running)

    def set_max_planning(self, max_planning):
        try:
            x = int(max_planning)
            if max_planning < 1:
                raise APIError("Value for max_planning must be >= 1: %s" % max_planning)
            self.max_planning = x
        except ValueError:
            raise APIError("Invalid value for max_planning: %s" % max_planning)

    def get_dir(self):
        return os.path.join(self.user.get_userdata_dir(), "ensembles", self.name)

    def get_object(self):
        return {
            "id": self.id,
            "name": self.name,
            "created": self.created,
            "updated": self.updated,
            "state": self.state,
            "max_running": self.max_running,
            "max_planning": self.max_planning,
            "workflows": url_for("route_list_ensemble_workflows", name=self.name, _external=True),
            "href": url_for("route_get_ensemble", name=self.name, _external=True)
        }
示例#3
0
class EnsembleWorkflow(db.Model, EnsembleMixin):
    __tablename__ = 'ensemble_workflow'
    __table_args__ = (
        db.UniqueConstraint('ensemble_id', 'name'),
        {'mysql_engine': 'InnoDB'}
    )

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    created = db.Column(db.DateTime, nullable=False)
    updated = db.Column(db.DateTime, nullable=False)
    state = db.Column(db.Enum(*EnsembleWorkflowStates), nullable=False)
    priority = db.Column(db.Integer, nullable=False)
    wf_uuid = db.Column(db.String(36))
    submitdir = db.Column(db.String(512))
    ensemble_id = db.Column(db.Integer, db.ForeignKey('ensemble.id'), nullable=False)
    ensemble = db.relationship("Ensemble", backref="workflows")

    def __init__(self, ensemble_id, name):
        self.ensemble_id = ensemble_id
        self.set_name(name)
        self.set_created()
        self.set_updated()
        self.state = EnsembleWorkflowStates.READY
        self.set_priority(0)
        self.set_wf_uuid(None)
        self.set_submitdir(None)

    def set_state(self, state):
        state = state.upper()
        if state not in EnsembleWorkflowStates:
            raise APIError("Invalid ensemble workflow state: %s" % state)
        self.state = state

    def change_state(self, state):
        # The allowed transitions are:
        #   PLAN_FAILED -> READY
        #   RUN_FAILED -> QUEUED
        #   RUN_FAILED -> READY
        #   FAILED -> QUEUED
        #   FAILED -> READY
        if self.state == EnsembleWorkflowStates.PLAN_FAILED:
            if state != EnsembleWorkflowStates.READY:
                raise APIError("Can only replan workflows in PLAN_FAILED state")
        elif self.state == EnsembleWorkflowStates.RUN_FAILED:
            if state not in (EnsembleWorkflowStates.READY, EnsembleWorkflowStates.QUEUED):
                raise APIError("Can only replan or rerun workflows in RUN_FAILED state")
        elif self.state == EnsembleWorkflowStates.FAILED:
            if state not in (EnsembleWorkflowStates.READY, EnsembleWorkflowStates.QUEUED):
                raise APIError("Can only replan or rerun workflows in FAILED state")
        else:
            raise APIError("Invalid state change: %s -> %s" % (self.state, state))

        self.set_state(state)

    def set_priority(self, priority):
        self.priority = validate_priority(priority)

    def set_wf_uuid(self, wf_uuid):
        if wf_uuid is not None and len(wf_uuid) != 36:
            raise APIError("Invalid wf_uuid")
        self.wf_uuid = wf_uuid

    def set_submitdir(self, submitdir):
        self.submitdir = submitdir

    def get_dir(self):
        ensembledir = self.ensemble.get_dir()
        return os.path.join(ensembledir, "workflows", self.name)

    def get_object(self):
        return {
            "id": self.id,
            "name": self.name,
            "created": self.created,
            "updated": self.updated,
            "state": self.state,
            "priority": self.priority,
            "wf_uuid": self.wf_uuid,
            "href": url_for("route_get_ensemble_workflow", ensemble=self.ensemble.name, workflow=self.name, _external=True)
        }

    def get_detail_object(self):
        def myurl_for(filename):
            return url_for("route_get_ensemble_workflow_file",
                           ensemble=self.ensemble.name, workflow=self.name,
                           filename=filename, _external=True)
        o = self.get_object()
        o["dax"] = myurl_for("dax.xml")
        o["replicas"] = myurl_for("rc.txt")
        o["transformations"] = myurl_for("tc.txt")
        o["sites"] = myurl_for("sites.xml")
        o["conf"] = myurl_for("pegasus.properties")
        o["plan_script"] = myurl_for("plan.sh")
        return o